8 ms·
Two Years of OCaml
- ggm 4y agoAlthough I read all of it, really? I'm in the syntax obsessive set. Interesting to read about semicolons improving comprehension -it felt like it had been decades since somebody had the courage to say so. (That said I write python un functionally and so am 4space tabbed to the max) It's also the first time I've seen "currying is bad" which seems to run against the flow of salmon.
- KingMob 4y agoLispers here, cackling with their S-expressions, listening to other languages complain about being unsure where a statement/expression ends.
- ggm 4y agoAs a non-lisper, it always kind of amused me that vi had brace-detection in the % command. I mean, what self-respecting C coder doesn't know where the other bracket is.. oh wait. ok. That's useful for me. Then you wind up in emacs, editing a .emacsrc file, marvelling at the .. depth of germanic (((( ... things) which need to be said)) by this person) nesting.. wondering what you do...
- pharmakom 4y agoYeah I understand why F# has whitespace indentation now - it resolves these ambiguities in OCaml without adding a bunch of new keywords.
- brmgb 4y ago> Interesting to read about semicolons improving comprehension -it felt like it had been decades since somebody had the courage to say so. (That said I write python un functionally and so am 4space tabbed to the max) I think it has a lot to do with the writer not using blocks. It would solve both of their issues (with match and with if and semi-colons which is actually an issue of precedence) Some people seem to have a lot of trouble with the BCPL/Pascal syntax using begin and end. The author apparently doesn't know about "|>" either which would solve their sequencing issues. At least this post was written in good faith. I think this highlights that there is a dearth of recent material promoting best practices when it comes to Ocaml.
- Georgelemental 4y ago> Type Inference is Bad > So when you make a mistake, you’re still giving constraints to the inference engine. Erroneous type inferences propagate in every direction. Error messages appear hundreds of lines of code away from their origin. Rust gets this right: it has type inference, but only within the function body. Most of your code is free of annotation cruft, but interfaces are strongly specified and errors can only propagate a certain distance.
- deleted 4y ago[deleted]
- yawaramin 4y agoThat's why it's idiomatic in OCaml to write interface files which contain type annotations for the modules. In practice many or most modules (over time) are given interface files which strongly contain the area of effect of type inference.
- IshKebab 4y agoIs it? I've only done a bit of OCaml (working on Sail) but that doesn't have any type interface files.
- rwmj 4y agoIn virt-v2v we eventually enforced that every module file also has a corresponding interface file: https://github.com/libguestfs/virt-v2v/blob/master/check-mli.sh https://github.com/libguestfs/virt-v2v/blob/master/check-mli...
- IshKebab 4y agoProbably if you need to do that it should just be enforced by the compiler. It's pretty clear to me (and the author of this post) that Rust got this right - small scale type inference is fine (in function bodies) but you really want explicit types for functions and up. Without that, you lose out massively on readability and error message quality. In Sail, I have IDE type inlays working but it barely helps with reachability because half the types are inferred as generic.
- snailscale 4y agoone thing I really like about Ocaml is the language adapts. Multi core, modular implicits, build systems. I imagine Ocaml will continue to adapt and while I don’t think it will solve all the authors problems with the language (syntax) it may solve some.
- IshKebab 4y agoI agree with almost all of this. And I'd add that using OCaml on Windows is so painful as to be effectively not possible. Where I slightly disagree: 1. I think expression based is fine. He's definitely right that OCaml does expressions wrong (it's very unclear where expressions end - I often end up adding and removing semicolons until the compiler stops complaining)... but I never have that problem in Rust. 2. Haskell's separation of the types of functions from the arguments is definitely not better. I don't want to have to manually count through two lists to match them up. And he correctly points out that currying is bad (overall) but at least OCaml sensibly separates arguments and return values, unlike Haskell which just checks them all in a -> separated list. But overall this is a great list. I'm sure OCaml and Haskell programmers will feel like the author doesn't "get it" but I think if they search their feelings they'll know it to be true.
- yawaramin 4y agoIt's also worth noting that the author says that even with these 'deficiencies', OCaml is still far above everything else :-)
- IshKebab 4y agoThey didn't actually go that far, but yes it's still better than many languages. I would say Rust solves almost all of the issues identified in this post. It obviously introduces the extra complexity of no GC & borrow checking, but if you're ok with that I don't see why you would pick OCaml over Rust.
- deredede 4y agoThe menhir parser generator is extremely good and doesn't quite have an equivalent in the Rust world. But other than that, in no particular order: - While it has its downsides, OCaml's module system (and functors especially) is extremely powerful and allows for all sorts of higher-kinded abstractions that are currently out of reach of Rust's type system, especially when combined with first-class modules - No monorphisation means more reasonable compile times - Some of the advanced type system features (GADTs, extensible types, polymorphic variants) are really quite nice (but really, menhir is great, and I miss it whenever I need to parse things in another language)
- tome 4y ago> When I see “applied to too many arguments” I know I added an extra one. Does anyone understand the complaint here? It sounds like the error message describes exactly what's wrong!
- stefncb 4y agoI don't understand the downvotes. I thought the same thing. I agree with the other complaint on the error for too few arguments being unfortunate, but the one with too many arguments is on point.
- dllthomas 4y agoI mean, it took me a beat to learn to actually read GHC error messages instead of jumping to where it's pointing in the code and assuming I know what's wrong. That's kinda the opposite of the complaint, though, except insofar as both involve learning.
- xupybd 4y agoHow do you get an invite for lobsters?
- lproven 4y agoAsk me nicely? :-)
- ernst_klim 4y ago> modules are worst I think the opposite, modules are vastly superior to typeclasses in regards to, well, modularity. > In Haskell, the type class database is global and there is no duplication. That's not a bug, but a feature of module system. > This lets you naturally compose implementations: for example, you can make it so that if a type A implements the equality type class Eq, and a type B also implements Eq, then the tuple (A, B) implements Eq in the obvious way. Unless you want a totally different ordering for A, which happens a lot in programming and even in math, where you can define many groups for the same set. https://existentialtype.wordpress.com/2011/04/16/modules-matter-most/ https://existentialtype.wordpress.com/2011/04/16/modules-mat...
- ubertaco 4y ago>There’s an easy way to solve this: add an end if delimiter. Again: terseness bites. I think this is the second frontpage post in a single week with someone talking about this exact thing, going on about how OCaml doesn't have braces or block-end signifiers....somehow completely missing `begin`...`end`, which has been part of the language since like forever? Just like with the last post, let's look at this post's example: let foo _ = if true then print_endline "Hello, world!"; true else false Yeah, I'm a little surprised that this doesn't work, actually, since I would assume that it would parse the if-branch until it gets an expression, but the compiler (and OCamlFormat, for what it's worth) interprets this code like this (and the auto-formatting done by ocamlformat makes it clear what's going on -- maybe consider hooking that up as an on-save action in your editor): let foo _ = if true then print_endline "Hello, world!"; true else false (which I discovered by just copy-pasting it directly into https://try.ocamlpro.com https://try.ocamlpro.com, which auto-formatted the code exactly like that for me). Basically "(if true then print); true" rather than "if true then (print; true)" Getting back to my original point, the code can easily be fixed by using `begin` and `end`: let foo _ = if true then begin print_endline "Hello, world!"; true end else false OCaml _does_ have braces, like in the "more-solid-feeling" languages the author describes. They're just named "begin" and "end" instead of "{" and "}", same as in Ruby or Elixir or Pascal or even Austral (which is the author's own language). This is, admittedly, more of a pain for dropping in a quick debug statement than what the author found: let foo _ = if true then let _ = print_endline "Hello, world!" in true else false ...which honestly, for the "quickly add a print-debug line" case, doesn't seem like a problem?
- ghostwriter 4y ago> Where Haskell is worse: > Infix operators are bad. Custom infix operators are worse. Disagree, as a regular user of `shouldBe` and other HSpec expectations, as well as DSL libraries that rhyme like English. And even when they don't rhyme, they provide flow for defining your complex types that would be tiresome to define with verbose prefixes (Servant). > Haskell is very indentation-sensitive, more so than Python. Slight, harmless-looking cosmetic changes can break the parser. That's not true, Python is more sensitive to indentations. > Lazy evaluation is bad. > Lazy data structures are bad. > Is purity worth it? Not really. These are just lazy crowd-opinions. > Every file starts with declaring thirty language extensions. This has never been true, all extensions can be declared default global to a compilation group (library/executable/project) and never mentioned in .hs files. When you see extensions being specified in every file of online tutorials, you know it's being done so for 1) didactic purposes 2) self-contained units for copy-pasting into your editor. All in all, the author isn't very well versed in Haskell, as it becomes clear with the provided examples of Ord instances for newtype IntAsc declarations. A seasoned Haskell programmer would almost certainly write it with `deriving via`, especially in a situation where they want to demonstrate how easy it is to get around the limitation of a single typeclass instance per type.
- tome 4y ago> > Every file starts with declaring thirty language extensions. > This has never been true, all extensions can be declared default global to a compilation group Yup, or nowadays you can just use "GHC2021" and be happy.
- JoelMcCracken 4y agoFor a discussion on combining the benefits of modules with type classes, see "Modular Type Classes"; If I were to implement a language with similar features today, I would certainly use it. https://www.cs.cmu.edu/~rwh/papers/mtc/full.pdf https://www.cs.cmu.edu/~rwh/papers/mtc/full.pdf
- hajile 4y agoI love the idea because it makes typeclasses possible, but not super-easy which means devs will be discouraged from making Haskell's typeclass soup.
- IshKebab 4y agoOh, another one that applies to all functional languages: why the obsession with singly linked lists? Ok I do actually understand why, but they're objectively the worst data structure yet they're made 1st clas - maybe 0th class! - language features. Kind of mad. I guess at least OCaml has normal vectors too, but still it always felt like a theoretical compsci feature that was almost willfully rejecting actual computer architecture.