3 ms·
I love FP and have programmed Haskell in professional contexts. But I have to admit, I don’t like it and it’s strong formalisms make so many problems much harde
by mruts 7y ago
I love FP and have programmed Haskell in professional contexts. But I have to admit, I don’t like it and it’s strong formalisms make so many problems much harder than they have to be.
Take lenses for example. All of this unnecessarily complicated shit because Haskell doesn’t have any reasonable record syntax.
I appreciate Haskell as a research project and it’s clearly pioneered many important FP concepts: monads, free monads, trampolines, etc. But I would never ever choose it for a new project. OCaml, F#, and Scala would be my go to. Nice FP, but not so opinionated to cripple/slow you down when you want to dip your toes in mutation. And in my experience, almost all non-trivial programs require at least a little bit of mutation. And when it’s required, I really don’t want to waste my time with IORefs or STRefs or whatever.
- antisemiotic 7y ago>Take lenses for example. All of this unnecessarily complicated shit because Haskell doesn’t have any reasonable record syntax. Lenses (in the original, pre-Laarhoven form) are literally the same as properties in, say, C#. The extra complexity in their modern form is to pack the setter and getter into a single function, and allow in-place modification (without going throgh getter and then back through setter). The extra-extra complexity in the lens package is the result of Edward Kmett et al generalizing it to support traversals and pattern matching, while also providing support for the entire standard library and the kitchen sink. As for mutation, I agree. I think Rust with hihgher-kinded polymorphism would be my ideal language.
- foldr 7y agoThere's always a reason of some kind for the additional complexity. The question is whether it's worth it. > The extra complexity in their modern form is to pack the setter and getter into a single function, and allow in-place modification (without going throgh getter and then back through setter In place updating of nested fields is pretty much the bare minimum that any respectable record system provides.
- antisemiotic 7y agoA record system doesn't allow to create fields from arbitrary getter-setter pairs. Lenses are an implementation of property system, not a record system. That the heavyweight solution is also used for regular records because Haskell's record syntax is broken is another matter. I still frequently wish I could use lenses in other languages, but they're hard to implement without HKT (I wouldn't be surprised if someone implemented them for Scala though). EDIT: And to clarify, by in-place updating I meant in-place semantically, not syntatically (the old solution of keeping a record of two functions can do the syntax part too). But I think I probably misremembered how van Laarhoven lenses work and they might not be ultimately different from getter-setter chaining, sorry.
- whateveracct 7y agoI don't think you ever need mutation in your business logic. I worked at a Scala shop that bought into immutability etc but was relatively green at it. There was always a pure FP way of solving a problem without mutability. Also I don't see how ST would especially slow you down if you really want to write pure function with mutability under the hood? It's an interface you have to learn, but the benefit is you _prove_ your mutations are locally-scoped.
- mruts 7y agoFor performance reasons mutability in Scala is often necessary. It was a financial shop and many things were too slow to just fold over. Closures are slow, and copying is slow. A lot of what we were doing was adding up and multiplying numbers. The difference in performance between, say, a while loop that adds up a variable in 1 million classes and a fold is so stark. Moreover it’s not just about performance. Right now I’m programming a bittorrent client in Scala with Akka and it would incredibly difficult to do without mutation. And the complexity overhead that Haskell requires for mutation just isn’t worth it in a lot of cases. I’m pretty good at determining if mutation doesn’t bleed into the outer scope and most of the time don’t want to pay the complexity overhead in actually proving. Sometimes you do want that of course, but not most of the time.
- quickthrower2 7y agoI'd like someone to blog about Haskell who has say an average IQ, has learned Haskell (used it professionally) and then can come back and talk to points like this. It seems a lot of Haskellers have super high IQ, and can grok Haskell Lens like it's a toy truck. Then they write a blog post that's pretty hard for a beginner to disect. Or maybe they struggled with Lens but by the time they spent 5 years with other gurus in a professional setting they finally got it, but have forgotten how hard it is to learn this stuff.
- kark 7y agoSee the “monad tutorial fallacy”: https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ https://byorgey.wordpress.com/2009/01/12/abstraction-intuiti...
- quickthrower2 7y agoAbsolutely - that's why I added the professional experience caveat. Someone who has just got a concept 5 minutes ago shouldn't write a tutorial about it.
- agentultra 7y agoLearning it is challenging but achievable by most interested programmers. It's vastly different than most mainstream languages so it's not as easy to pick up as C# is to a C++ programmer because so few concepts translate from C++ to Haskell. But it's not impossible if you're seriously interested. You also don't have to learn all of it to start using it. The majority of code I write in Haskell doesn't use anything more fancy than function composition, ADTs, and some type classes. You can do programming at the type level but that's not a requirement for entry.
- aeneasmackenzie 7y agoLenses are much more powerful than just records. It's programmable ., too borrow the metaphor.
- thinkpad20 7y agoI wish Haskell had better syntax for records, but to be honest it’s very rare that it actually presents a real issue in practical code that I write. Sure, it can be a bit awkward to update nested records, but I struggle to think of more than a few cases where it’s caused me any real grief, and even then it was only an issue of convenience (having to write a slightly more awkward line of code) as opposed to causing bugs or preventing a satisfactory solution to a problem. I readily admit it’s something that could be improved, but I think it’s more of a hobby horse than a real problem. YMMV of course. For what it’s worth, I’ve written tens of thousands of lines of Haskell over the past few years and have barely ever used lenses. They’re really there as a convenience for people who are familiar with them. Understanding lenses is by no means a prerequisite to writing practical code in Haskell. I find it hard to co-sign on your assertion that all non-trivial programs require mutation. This hasn’t been my experience at all. While having access to side-effects is certainly essential (which Haskell is fully capable of doing), mutation is quite rarely needed in my experience. In the cases that it is, IORefs are trivial to use. On top of that Haskell has MVars, which I hazard to claim are the best concurrent mutation primitive I’ve ever had the pleasure of using. Quite the opposite of being crippled.
- tome 7y agoYou might like to take a look at the de facto standard Haskell introductory textbook, http://haskellbook.com/ http://haskellbook.com/, by Christopher Allen and Julie Moronuki. They are not category theoretical geniuses. Julie is from a linguistics background I think.