5 ms·
Another Haskeller here. I strongly recommend you take a second look at OCaml. I think it has some fantastic features that Haskell doesn't: Modules. They are gr
by GreaterFool 12y ago
Another Haskeller here. I strongly recommend you take a second look at OCaml. I think it has some fantastic features that Haskell doesn't:
Modules. They are great for solving major code organisation problems and I really hope Haskell will get a module system soon ("Backpack" paper). Type classes are great for things like Monad and Num since you are likely to use many different Monads or Nums in the same chunk of code. But consider what happens if you want to support both ByteString and Text in your library (let's say a parser library). You may end up with a type class constraint like ListLike and your code will be littered with 'ListLike .. =>'. But when you're parsing some data later on it will be either ByteString or Text. So I'd fix my choice of ListLike at module instantiation time and make the constraint go away. If I need both (e.g. I'm reading some data from a socket and some of it is Text and some of it is ByteString) then I'm just going to instantiate two modules, one for each. To me this is a much cleaner solution.
Named/optional function parameters. They solve a bunch of minor but incredibly annoying problems. A simple example: for (aka flip map); It is not in Prelude and whenever it comes up there are plenty of people who are opposed for one reason or another. In OCaml (Core library) it doesn't matter because map takes the function by named parameter so List.map ~f:(fun x -> x + 1) [1;2;3] works fine and so does List.map [1;2;3] (fun x -> moderately long, perhaps few lines long function). Both cases are important for readability. Another example: in Haskell I've been working with APIs where functions have 20+ positional parameters (yeah, it's terrible design but that's out of my hands). If they were named and some of them optional (most of them really are optional) then the code would be a fraction of what it is.
OCaml is quick to compile. I've been looking at Eliom web framework recently and rebuilding a website takes seconds; compare that to yesod which takes forever and spins all the cores on my laptop which eats my battery in no time.
OCaml code tends to be quite straightforward: from my experience it is longer than Haskell equivalent, uses less abstractions but at the same time it is conceptually simple.
Typed printf. (yeah, there are 'solutions' in Haskell but it's a typed printf out of the box!)
Polymorphic variants. Can be used to bring information to the level of types. Compare
parse :: Parser a -> String -> ParseResult a
with
parse :: Parser a -> String -> [`Error String | `Result a]
Also see OCaml's tyxml package which provides typed html5. Yeah, the types look rather crazy in some places but that's a small price to pay for rooting out invalid HTML.
- shadytrees 12y agoHaskell has typed printf out of the box! It recently (v4.7) got a makeover so now it's extensible too. https://hackage.haskell.org/package/base-4.7.0.0/docs/Text-Printf.html https://hackage.haskell.org/package/base-4.7.0.0/docs/Text-P...
- GreaterFool 12y agoYou are indeed correct in that printf has a type. However what I mean when I say OCaml has typed printf is this: utop # printf "%d\n" "foo!";; Error: This expression has type string but an expression was expected of type int versus what happens in Haskell: λ printf "%d\n" "foo" * Exception: printf: bad formatting char 'd' OCaml has compiler level support for format strings. "%d" and friends get parsed into a GADT at compile time and printf "%d" has type int -> unit In Haskell PrintfType => type-class magic is used to make printf accept a variable number of arguments. However, the types of those arguments are not checked against the format string (since the format string is just a string). Hence the error happens at runtime and Haskell's printf is effectively untyped. It is not very hard to implement printf that takes a GADT and and has a proper type (e.g. Int -> String) and there are libraries that do something along these lines (see formatting library on Hackage; there's also a template-haskell based solution that uses a quasi-quoter [fmt|%d\n|]). But I do prefer the elegance of c-style format strings. Besides OCaml has this out of the box and in standard library while Haskell printf is dangerous and should be avoided. Even C++ is better -- I've seen compilers/linters throwing warnings at me when arguments didn't match the format string. Printing to stdout/stderr shouldn't be hard and shouldn't be something one needs third-party libraries to do nicely. Hence I've put it on the list.
- cordite 12y agoThis does make me want to take a look OCaml seriously. I'd mostly use it in a web server context. Though I have no clue where to really get started in that. Yesod actually was one of the reasons that pushed me to learning Haskell (though I arguably never got much done in Yesod since it felt like its pragmatisms didn't match up with mine.)