5 ms·
There are many similar warts in the ocaml type system. Parametric polymorphism in ocaml sucks as well. If you haven't tried haskell, you probably should. Its
by wyager 4y ago
There are many similar warts in the ocaml type system. Parametric polymorphism in ocaml sucks as well.
If you haven't tried haskell, you probably should. Its type system is much cleaner (and more powerful, if you want) than ocaml's, and many details of Rust are derived from Haskell.
- octachron 4y agoParametric polymorphic is the same in OCaml and Haskell. Did you meant to say that the value restriction does not play nicely with point-free programming?
- wyager 4y agoThat's one aspect of it. The ergonomics are dogshit. I remember having to use explicit quantification all the time when writing polymorphic library code. Also, without typeclasses, polymorphism is super inconvenient, to the point where it's almost exclusively used in the most critical data structures like sets and maps. It's not "the same as in haskell" except maybe in the very vague sense that they have similar underlying type theories (although ocaml's is much weaker - e.g. I remember needing to use some hacks to approximate HKTs, while haskell handles them easily).
- octachron 4y agoOCaml does not require more annotations than Haskell for polymorphic functions? Both language only require annotations in the case where inference would be undecidable (polymorphic recursions, higher-rank polymorphism, and GADTs). I know few cases where OCaml require less annotations than Haskell, I would expect the reverse to be true. And maps and sets are not the main use case for polymorphism in OCaml. Even taking in account that it sounds like you are talking about functors, maps and sets are still not the only instance of functors in OCaml.
- wyager 4y ago> OCaml does not require more annotations than Haskell for polymorphic functions? A) I am fairly confident this is not actually true in a technical sense, although it's been several years since I've thought about it B) In any case, in the (many) instances where you (by rule or convention) need to put a type signature on your function (e.g. because it's a top-level function, one that you export, etc.), it is a pain in the ass to make it polymorphic in ocaml compared to in haskell. > Even taking in account that it sounds like you are talking about functors No, I'm not, although ocaml people tend to think exclusively in "functors" (badly named, in my opinion - conflicts with the more common category-theoretic definition) because the experience of using actually parametric functions is so bad that they almost never do it.
- octachron 4y agoDo you have any examples? Unfortunately from my perspective, I cannot make sense of your statements. OCaml typing is principal in all situation where type inference is decidable. The syntax for annotation for polymorphic functions is isomorphic between OCaml and Haskell. If I take a random module in the standard library, let's say Array, 95% of the functions in this module are parametric polymorphic. I am thus genuinely puzzled by your statement that "OCaml programmers almost never write polymorphic functions".
- wyager 4y agoI wrote up a bunch of grievance examples for a blog post I never got around to publishing, but I'm traveling at the moment so can't pull up my laptop. I'll see if I can find them later. > The syntax for annotation for polymorphic functions is isomorphic between OCaml and Haskell. Sorry, but total bullshit. I had to use these pieces of shit all the time. https://v2.ocaml.org/manual/locallyabstract.html https://v2.ocaml.org/manual/locallyabstract.html > If I take a random module in the standard library, let's say Array As I specifically called out, all the core data structures are polymorphic. (Let's not talk about the float array hack; is that still around?) It's so annoying that pretty much every other library is monomorphic or functorized. > I am thus genuinely puzzled by your statement that "OCaml programmers almost never write polymorphic functions". Not sure what to tell you man. I spent 4 years reading & writing ocaml and 95% of the code that would have been polymorphic in haskell (because it would be easy/free) was either monomorphic or (multiple layers of) functors. Many/most of the devs I worked with (great devs with years of OCaml experience) didn't even know what LATs were, let alone used them, which means they were almost certainly not writing polymorphic code which "did anything" with the type. The only polymorphic code that you can write in ocaml without such things are functorial (in the categorical sense, not the ocaml sense). Arrays, map values, that's about it.
- abathologist 4y agoHaskell is a great language but has plenty of its own warts. The value prop and trade offs between OCaml and Haskell really makes it hard to use one as a drop in for the other imo.
- wyager 4y agoStrong disagree; I have thousands of hours with both and I would essentially never recommend ocaml over haskell unless your company already has an ocaml codebase/ocaml expert employees. I'm very conscious of the existence of pareto tradeoffs; I am asserting that, in this case, there is essentially no tradeoff to be made. Haskell is equal or better (sometimes significantly so) in almost every relevant domain. For domains in which ocaml is a better choice, it is not the globally best choice (i.e. both ocaml and haskell are bad in those domains).
- substation13 4y agoWhat about the performance challenges caused by lazy evaluation?
- belmont_sup 4y agoFresh in both languages. But on studying the Effective Haskell book, there's a whole chapter (chp 14) on learning how to read and write efficient and faster Haskell code. Training that mental model of understanding how IO gets evaluated didn't seem too difficult. It feels akin to remembering how to write fast SQL code - you just practice a bit and measure. In chp 7 on understanding IO, there's also another great section that explains how IO evaluation is often confused. I share an example from the book that reads, writes, and prints files. Memory intensive func because it attempts to read _all_ files at once because the execution of reading and writing actually only happens when the print fn is called (putStrLn files). makeAndReadFile is actually doing both reading and writing - a normal task in all other languages. slow = let files = mapM makeAndReadFile [1..500] :: IO [ String ] in files >>= (putStrLn . show) Efficent version. Here we force reads and writes to actually occur per file instead of waiting til the print. Seems like a pretty easy step to misunderstand. safe :: IO () safe = foldl ( \ io id -> io >> makeAndShow id ) (return ()) [1..500]