knz / drknz

Comments for the web site at dr-knz.net
0 stars 0 forks source link

https://dr-knz.net/haskell-for-ocaml-programmers.html #5

Open utterances-bot opened 3 years ago

utterances-bot commented 3 years ago

Haskell for OCaml programmers · dr knz @ work

This post mirrors OCaml for Haskellers from Edward Z. Yang (2010). Note The latest version of this document can be found online at https://dr-knz.net/haskell-for-ocaml-programmers.html. Alternate formats: Source, PDF. Prologue Why write a new post when a clever reader could simply “read Edward’s post backwards”? It …

https://dr-knz.net/haskell-for-ocaml-programmers.html

shenlebantongying commented 3 years ago

I am curious about what markup language and what tool are you using to convert the source to pdf & html?

I tried org-mode and asciidoc, but seems not right.

knz commented 3 years ago

This is restructured text (rst).

shenlebantongying commented 2 years ago

There seems to be a typo. It doesn't work on ghc9.2

instance Eq Peano where
    (==) Zero Zero = True
    (==) (Succ x) (Succ x) = (x == x)
    (==) _ _ = False

Should be

    (==) (Succ x) (Succ y) = (x == y)
knz commented 2 years ago

@shenlebantongying: good catch! Thanks. Fixed.

oshyshko commented 1 year ago

{- "|>" not predefined in Haskell -}

It's called (&).

ninjaaron commented 2 months ago

Thanks for this helpful article! I'm learning Haskell now as an experienced OCaml programmer, and it's nice to have a quick reference. One critique I might offer is concerning your monad tutorial that refuses to use the word "monad".

My impression is that most OCaml programmers understand monadic interfaces fairly well. OCaml's ecosystem makes extensive use of monadic style for handling errors with the Result monad and the Option monad.

In addition, anyone who has done any kind of network programming in OCaml is likely to have encountered monadic IO working Jane Street's Async library or (more likely) Lwt.

It might therefore be useful to enhance your Haskell monad "recipe system" tutorial by using analogies with the numerous monadic types OCaml programmers encounter on a regular basis.

ninjaaron commented 2 months ago

e.g.

module StrMap = Map.Make(String)

let add_keys map key1 key2 =
  let ( >>= ) = Option.bind in
  StrMap.find_opt key1 map >>= fun a ->
  StrMap.find_opt key2 map >>= fun b ->
  Some (a + b)

(* also written as... *)
let add_keys map key1 key2 =
  let (let*) = Option.bind in
  let* a = StrMap.find_opt key1 map in
  let* b = StrMap.find_opt key2 map in
  Some (a + b)

let () = 
  let my_map = StrMap.of_list ["foo", 1; "bar", 2; "baz", 3] in
  assert (add_keys my_map "foo" "bar" = Some 3);
  assert (add_keys my_map "foo" "qux" = None);
  assert (add_keys my_map "qux" "foo" = None);
  assert (add_keys my_map "qux" "qux" = None);
knz commented 2 months ago

Hi Aaron, Thanks for the feedback.

One thing to keep in mind however is that Haskell's design goes to great length to hide the mechanics of monadic notation, so that the programmer can switch in their mind to imperative style. This is sadly not so with ocaml, which doesn't provide syntax shortcuts (fundamentally, because of lack of operator overloading). Therefore, I do not believe that it is very useful to emphasize ocamls monadic facilities, a newcomer to Haskell would do better to grow new intuitions from scratch.

What do you think?

ninjaaron commented 2 months ago

Hm. Maybe, maybe. I think defining let* within a certain scope gets pretty close to do notation, and many modules take this farther, adding a "Syntax" module to open in your scope that supply bind and map syntax (let* and let+ respectively, or let%bind and let%map for older code) in addition to a return function.

As usual, the OCaml approach is more verbose than what Haskell offers, but I'm pretty sure that working with Lwt is what really made monadic IO "click" for me in Haskell, together with understanding callback functions in other asynchronous programming contexts (i.e. the DOM).

YMMV, but for me, understanding that I/O works in Haskell in terms of callback chaining was a breakthrough in understanding why code using do notation in Haskell sometimes behaves quite differently than code which looks similar in imperative languages. It becomes much more obvious in de-sugared code---not that I'm against the sugar, just that it was unhelpful for gaining an initial understanding of Haskell's behavior.

On the other hand what works for me may not work for everyone, and it's your tutorial. Perhaps some people will get more out of visualizing monadic control flow as the construction of a recipe than thinking about it in terms of callback chaining.