<discocaml>
<drupyog> mmh, indeed, maybe that would be an interesting way to go forward
<discocaml>
<drupyog> @wasla note that this is not so different from having several llvm installed and using the old C-API from OCaml, which mostly works fine
<discocaml>
<drupyog> thanks, I discovered that. It should probably be made apparent in the packet metadata ...
YuGiOhJCJ has quit [Quit: YuGiOhJCJ]
<discocaml>
<wayneyam> is there a way of understanding monads, applicatives, functors in a OCaml point of view?
<discocaml>
<wayneyam> I was reading typeclassopedia and I just don't understand it
<discocaml>
<wayneyam> what even is "effectful computation"
<discocaml>
<wayneyam> and "programmable semicolon"
<discocaml>
<gooby_diatonic> Have you ever used Lwt? `Lwt.t` is a monad
<discocaml>
<wayneyam> no 😢
<olle>
purity vs effectful programming - effectful has side-effects, i assume they mean?
<olle>
side-effects are things that are not part of the contract of a functions input and output
<olle>
like read/write to IO, throw exception, randomize
<discocaml>
<gooby_diatonic> The pragmatic™ way of seeing monads is as an interface a type satisfies, that generalises something that can be chained (or a generalisation of CPS)
<discocaml>
<gooby_diatonic> Where the interface is bind, return etc
<discocaml>
<wayneyam> I think I understand this with `Option` , like it's convenient to chain computation with optional output
<discocaml>
<gooby_diatonic> You can see monads intuitively as boxes (or commonly burritos) that hold values (conceptually, they could be future values too)
<discocaml>
<gooby_diatonic> And bind is a programmable semicolon because it fully controls the way the computation will proceed and can also, e.g., do early termination (unlike fmap)
<discocaml>
<wayneyam> I don't understand "some monads allow us to write code as if it has side effects"
<discocaml>
<wayneyam> at least not with `option`
<olle>
the IO monad?
<olle>
Not needed in ocaml since ocaml is not pure
<olle>
but yea, still
<discocaml>
<wayneyam> yeah I don't understand what is the idea behind IO being a monad
<discocaml>
<wayneyam> I can't make it fit inside the "box" interpretation
<olle>
"Box" is a bit loose
alfiee has joined #ocaml
<olle>
I never understood IO monad either, so, I'll be happy to see a good explanation. :)
<discocaml>
<wayneyam> do you mean that bind specify the evaluation order of an expression?
<discocaml>
<gooby_diatonic> Sure you can, `readLine` is `IO String` (in Haskell) to signify it's a box that holds String but the value is only available once the user actually enters a value (bind handles this)
alfiee has quit [Ping timeout: 244 seconds]
<olle>
I guess it's similar to JS Promise?
tri has joined #ocaml
tri has quit [Ping timeout: 268 seconds]
<discocaml>
<octachron> A point that I think is important is that monads are quite abstract and thus "shapeless". It may work better for you to study a variety of instance monads before trying to get an intuition for what is a monad.
<discocaml>
<octachron> For IO, it is easier to start with a simpler embedded domain language
<discocaml>
<octachron> I like Random better for instance. But you can start with an "User_input" user monad.
<discocaml>
<gooby_diatonic> olle: Yeah exactly, Promise is a good intuition I'd say
<olle>
Or just don't learn monads, there are better things to spend braincells on ^^'
<discocaml>
<wayneyam> yeah, are they important to know
<discocaml>
<wayneyam> I actually don't know any Haskell 😢
<discocaml>
<gooby_diatonic> I mean that in `m >>= f`, the return value is fully dependent on `f` since it specifies how to construct the resulting value based on what is contained in `m` (or at least, a monad should behave something like that, I say should because it's not enforcable in the language). On the other hand, in e.g. `(fmap f) m`, the return value is really constructed by `fmap` (which defines the "unwrapping" and "wrapping") and `f` is simply used in t
<olle>
let* is flattening monadic code in ocaml no?
<discocaml>
<gooby_diatonic> Yessir
<olle>
bitter they never ported that general solution to rescript, but instead went with less generic async/await
<discocaml>
<gooby_diatonic> But I think writing continuations manually is a good exercise for those trying to wrap their head around monads
Haudegen has quit [Quit: Bin weg.]
<olle>
contiuanations, as in scheme? o0
<discocaml>
<gooby_diatonic> olle: Tbf, Rescript probably benefits more from async/await given its goals
<olle>
continuations*
<olle>
yes perhaps
<discocaml>
<gooby_diatonic> If you mean call/cc then those are continuations but a specific type, that which wraps the remaining execution context
<discocaml>
<gooby_diatonic> A continuation in general is just a function that represents the rest (or continuation) of some computation
<olle>
Hm!
<discocaml>
<gooby_diatonic> In the case of monads the `f` in `m >>= f` is a continuation
<discocaml>
<gooby_diatonic> Since you can see `m` as one fragment of the overall computation `m >>= f`
<olle>
lambda chains forever?
<discocaml>
<gooby_diatonic> Of course, praise be to lambdas
rgrinberg has quit [Ping timeout: 252 seconds]
<discocaml>
<wayneyam> so `(fmap f) m` depends on both `fmap` (of the underlying functor?) and `f` while `m >>= f` only depends on `f`
<discocaml>
<Fardale> In a new switch, the installation of `odoc-parser` fails with `Unbound module "Stream"` with ocaml 5.3.0. With a quick search, I did not find anything.
rgrinberg has joined #ocaml
<discocaml>
<gooby_diatonic> That's the idea yeah, of course in reality `>>=` can also have an arbitrary definition, but the expected behaviour (we trust the library developers here) is that it will extract the contained value from `m` (as `f` depends on it) and then `f` does the rest of the work (which is suggested by it's type signature `'a -> 'b m`)
<discocaml>
<gooby_diatonic> OCaml makes it pretty quite with `let*`
<discocaml>
<gooby_diatonic> cute*
<discocaml>
<wayneyam> it looks very helpful but I still don't understand it 😅
<discocaml>
<wayneyam> will do it tomorrow when I'm less sleepy......
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 244 seconds]
<discocaml>
<Fardale> The problem was that I built the switch with the system compiler without noticing.
Serpent7776 has quit [Ping timeout: 265 seconds]
Haudegen has joined #ocaml
rgrinberg has quit [Ping timeout: 252 seconds]
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 244 seconds]
emp has quit [Ping timeout: 244 seconds]
emp has joined #ocaml
rgrinberg has joined #ocaml
alfiee has joined #ocaml
tri has quit [Remote host closed the connection]
tri has joined #ocaml
alfiee has quit [Ping timeout: 248 seconds]
tri has quit [Ping timeout: 276 seconds]
wbooze has joined #ocaml
Inline has joined #ocaml
Inline has quit [Ping timeout: 246 seconds]
wbooze has quit [Ping timeout: 252 seconds]
tri has joined #ocaml
tri has quit [Ping timeout: 268 seconds]
olle has quit [Ping timeout: 252 seconds]
alfiee has joined #ocaml
tri has joined #ocaml
alfiee has quit [Ping timeout: 248 seconds]
rgrinberg has quit [Ping timeout: 276 seconds]
Serpent7776 has joined #ocaml
rgrinberg has joined #ocaml
tri has quit [Ping timeout: 248 seconds]
<discocaml>
<diligentclerk> values in the IO monad are "lazy." That's what makes it box-like in my opinion - an IO string is not a string, it's a computation that you can run to get a string.
<discocaml>
<diligentclerk> Moggi, the original author who applied monads to computer science, thought of elements of a monad type as "computations"
tri has joined #ocaml
<discocaml>
<diligentclerk> the fact that IO values are lazy is I think a key part of the design, because the way Haskell works is that only the "Main.main" value actually gets computed, so if you want to perform IO you have to explicitly incorporate that into the Main.main value
<discocaml>
<noahtheduke> lol looks like that's probably changing. i hope this helps contributors in the future
<discocaml>
<noahtheduke> my experience with opening a PR this week was positive even tho it was rejected
rgrinberg has quit [Ping timeout: 260 seconds]
tri has quit [Ping timeout: 252 seconds]
tri has joined #ocaml
rgrinberg has joined #ocaml
tri has quit [Ping timeout: 260 seconds]
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 268 seconds]
tri has joined #ocaml
Inline has quit [Ping timeout: 244 seconds]
wbooze has quit [Ping timeout: 244 seconds]
tri has quit [Ping timeout: 260 seconds]
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 244 seconds]
rgrinberg has quit [Ping timeout: 272 seconds]
tri has joined #ocaml
tri has quit [Ping timeout: 252 seconds]
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 268 seconds]
tri has joined #ocaml
tri has quit [Ping timeout: 252 seconds]
tri has joined #ocaml
tri has quit [Ping timeout: 248 seconds]
Serpent7776 has quit [Ping timeout: 244 seconds]
alfiee has joined #ocaml
alfiee has quit [Ping timeout: 265 seconds]
bartholin has quit [Quit: Leaving]
Tuplanolla has joined #ocaml
<dh`>
grr
<dh`>
I wish if you had module A with a type t, and module B with type t = A.t, that opening both would not cause the compiler to gripe about t being ambiguous