12 ms·
Why Learn Haskell? (2018)
- 3np 6y agoI had a period of a couple of years in uni when I was very into Haskell and using it whenever it made sense to me (which was a lot). I haven't touched it many years (save for the occasional amending of my xmonad conf) and would need a lot of time to get back to reading it properly, let alone code in it. Still, I'm very happy I did that and look back at it fondly. It got me grokking the functional mindset and paradigm that still influence the design choices I make and the code I write heavily. Today, I'd push for learning Idris instead, or maybe using Haskell as a brief intro to Idris. While young, it's a lot more approachable and makes working with statefulness and IO a lot more intuitive, without sacrificing purity.
- txdv 6y agoCan you explain why someone would strive for "purity"?
- 1-more 6y agoNot op but they may mean the term-of-art where a pure function has no internal state and no side effects, so it always has the same outputs given the same inputs. Although it's not technically part of the definition of functional purity, I'd add that's it's nice to have a function whose behavior is defined for every input in the domain.
- jonathanpoulter 6y agoEase of testing is the most obvious benefit. A "pure" function is one whose result is simply based on its inputs, no dependency on external state/IO etc. Same inputs, same outputs guaranteed. These types of functions, are really easy to reason about and unit test. State is often messy.
- arcsin 6y agoWhen a variable can be reassigned it adds the complexity of time dependence. Meaning that if you don't keep track of the order of values that variable was assigned then you probably can't understand the program. The problem is compounded by the size of the scope that variable exists in. That's why we avoid using global variables, globals force us to track the order of updates from potentially anywhere in the code. The problem is further compounded if there are multiple globals that depends on each other. Then you need to track the relative order of updates across all globals. That's the worst case scenario. In OOP you try to limit the scope of state, private variables inside an object can update its value but can only be directly accessed from inside the object. But still those objects are inherently stateful. In order to understand an object, how you can use it, whether it is working correctly, you are still forced to understand where/when it is in the timeline of updates. Purity means that if you understand a variable or object in one place in your code then you understand it from anywhere in your code. You don't need to know how it was used before because it can't be changed. If it were changed then you would know because it would now be a different variable or object.
- jerf 6y agoI echo the sibling comments to my comment here. I would further add that in day-to-day code, I don't necessarily write "pure" functions. I use a strategy based on my experiences with Haskell, but spiced with a bit more pragmatism. For any significant bit of code past a couple of screens or so, I almost always have a clean separation between the "business logic" code, and the "IO" code, such that I can plug different "IO" codes into the business logic code trivially. The business logic code is not technically "pure", in that it calls out to IO code freely. But it means I can swap out the IO code for testing, and drive the business logic with any input I desire in the process. It also lets me test the IO code directly if that is useful/necessary/desirable, without the business logic getting in the way, which it often does! Theoretically, you could transform this to "pure" code, by gathering everything into one big data structure in the IO code, then feeding it to the business logic, but this often comes with a lot of inconvenience and even performance issues (like gathering expensive things you might need but not using them). One of the things that Haskell can "put into your fingers" is a sense of what code does IO. Even if you nominally know, you probably don't instinctively know if you've never used a language that rigidly forced you to be correct. It is a common experience for quite a while in Haskell to write a pure function, that calls a pure function, that calls a pure function... that, err... needs to read just a little bit from a file according to the way you've structured things. Whoops. And you learn to restructure things to move the reading back "up" in the code to constrain the purity, even though it's just a "little bit", and over time you get better at not making the mistake in the first place. If you are not trained by Haskell, it is really easy to end up thinking "oh, it's just a little bit of impurity... it'll be fine"... and maybe, in fact, it will. But this still starts to add up. I still write "impure" code... but I do so much more carefully now.
- ModernMech 6y agoThe number of times students have come to me absolutely baffled as to why they can't tokenize a string twice using strtok() is the best reason for function purity I can think of. It's such an abomination of a function. The first time you call it, you give it a string and a delimiter. Subsequent times you call it, you give it a NULL and the delimiter. And then once you've tokenized the string once, you can never use it again. It's an example I hold up of how not to design functions.
- carapace 6y agohttps://en.wikipedia.org/wiki/Referential_transparency https://en.wikipedia.org/wiki/Referential_transparency > An expression is called referentially transparent if it can be replaced with its corresponding value (and vice-versa) without changing the program's behavior. This requires that the expression be pure, that is to say the expression value must be the same for the same inputs and its evaluation must have no side effects. > In mathematics all function applications are referentially transparent, by the definition of what constitutes a mathematical function. However, this is not always the case in programming, where the terms procedure and method are used to avoid misleading connotations. In functional programming only referentially transparent functions are considered. > The importance of referential transparency is that it allows the programmer and the compiler to reason about program behavior as a rewrite system. This can help in proving correctness, simplifying an algorithm, assisting in modifying code without breaking it, or optimizing code by means of memoization, common subexpression elimination, lazy evaluation, or parallelization. > The concept seems to have originated in Alfred North Whitehead and Bertrand Russell's Principia Mathematica (1910–13). It was adopted in analytical philosophy by Willard Van Orman Quine.
- pliftkl 6y agoPersonally, I've written zero lines of production Haskell code, and expect that this will still be true when I retire. Despite that, learning Haskell was probably one of the best things that I've ever done. The learning process sent me down lots of interesting rabbit holes of language design, and certainly made me a more disciplined developer in other languages. The lambda calculus and predicate logic discussed in this article was one of the enjoyable rabbit hole trips induced by Haskell, but it was only one of many.
- nandhinianand 6y agoPlease do write about other rabbit holes too.. ..If not a long form article, a short compilation of the holes (and links if you can find the time to get them) would be very useful.. I've been interested and flirting with haskell for a while, but become too time-poor the last 4-5 years to do anything even hobby level.
- alpaca128 6y agoI don't know Haskell, but I'm pretty certain that something I recently discovered also applies there: Dependent Types In short, it's a way to restrict the data types to such a degree that the type checker can do compile-time checks of array sizes and other interesting things, as those aspects are directly expressed as distinct types depending on each other. The principle requires a pretty powerful type system and is cumbersome to use, but I found it fascinating regardless.
- exdsq 6y agoCheck out type-driven development (there are books on using Idris for this) -- it blew my mind! You do what you're talking about to encode business logic that's checked at compile time.
- vram22 6y agoI had checked out F# for a while, some time earlier. IIRC, it has some features like that, for encoding business logic in code/types. Probably some other languages do too. I had mainly used Scott Wlaschin's site F# for Fun and Profit, and MS sites, for F#. Edit: Also had looked at OCaml, via Real World OCaml, and also much earlier, via INRIA / O'Reilly sites / books / software. F# may be based on OCaml. Both resources are free to read online.
- atc 6y agoMy favourite language by far. I miss it when writing rust, ts or Java. I refuse to forget it!
- Shish2k 6y agoI love the things I learned from Haskell, but I find it so painful to actually use :( Similar case with Erlang... I wonder if there are any functional languages that aren’t weird? Like they call the first element in a list / the other elements “list[0]” and “list[1..]” instead of “car” and “cdr”? Bonus points for a C-inspired syntax rather than an abstract-mathematics-inspired syntax For now I just write Rust and Python using functional-style design (const inputs, no side effects, etc), but I feel like I’m missing out...
- nudpiedo 6y agoThere are some advantages in the syntax and reasons to be for all these things. I would recommend to start with a sweet intermediate step in which you may like more the domain you are going to program, for example if you are into web frontend go with Elm, if you like the dotnet ecosystem, server programming and mobile go with F#, and you may want to check clojure or prolog in order to understand why a homoiconic syntax is later important. Make the effort, it pays off when your brain clicks
- akdor1154 6y agoF# is what you want!
- omniscient_oce 6y agoIf you want a C-style syntax then ReasonML maybe?
- forkerenok 6y ago> Similar case with Erlang... Have you tried Elixir? I had been doing Ruby for a long time (also Java and Scala before and after that, now Python). Gave Elixir and Phoenix framework a shot a month ago and it's a breath of fresh air: great language, outstanding tooling. I've also done a bit of Haskell, OCaml and PureScript within my personal projects. I do miss having a state of the art typing in Elixir, but there is enough in Elixir to keep me happy: * immutability everywhere * ridiculously low latencies (not by HFT standards I guess) * LiveView * ...many other goodies that come with BEAM * Tooling edit: formatting
- siraben 6y agoReading Ben Lynn's Haskell website was one of the things that got me out of a rut with learning Haskell and showed me how expressive, yet concise it is. There's a lot of advanced and beginner Haskell resources but not much intermediate. I highly recommend his Haskell series, Lambda Calculus series[1] and (my favorite) compiler for Haskell series[2]. It's as if SICP were redone in Haskell in the 21st century. [1] https://crypto.stanford.edu/~blynn/lambda/ https://crypto.stanford.edu/~blynn/lambda/ [2] https://crypto.stanford.edu/~blynn/compiler/ https://crypto.stanford.edu/~blynn/compiler/
- mrslave 6y agoFilling in your [0]th link. Thank you so much for this pointer. [0] https://crypto.stanford.edu/~blynn/haskell/ https://crypto.stanford.edu/~blynn/haskell/
- fuzzypixelz 6y agoThis is exactly how I imagine proficient Haskellers spend their time on top of the ivory tower
- haolez 6y agoI'm thinking of starting this journey with PureScript. Seems a lot more practical for my use cases and their introductory book is quite good (I'm reading it).
- cies 6y agoYes. Or Elm. It'd advise that approach, as starting with Haskell is quite a big step. The https://haskellbook.com https://haskellbook.com is a great start though for anyone that wants to be guided through the basics.
- leke 6y agoI'm actually interested in Haskell now after I learned an interesting crypto startup called Cardano uses it and stakes (pun intended) its success on it. They toute the safety and maintainability for their choice, claiming it's the language of choice for banking institutions (if my memory serves me correctly). Found the video - https://www.youtube.com/watch?v=CffrvwIW0JY https://www.youtube.com/watch?v=CffrvwIW0JY I'm currently a web developer, but the blockchain scene is quite interesting. Especially these new smart contracts look quite easy to play around with.
- christiansakai 6y agoI believe Cardano will re-ignite the interest in Haskell.
- lelanthran 6y ago> They toute the safety and maintainability for their choice, claiming it's the language of choice for banking institutions So is COBOL. Doesn't mean anything, really. Bankers' choices in tech probably has nothing to do with ideological/purity issues in software development.
- exdsq 6y agoIt's to do with the ability to formally reason about the code using formal methods/verification etc...
- agumonkey 6y agoIIUC there's another crypto/dapp thing, but in ocaml. I guess safe and fast fp appeals to distributed finance.
- longngn 6y agoIt's Tezos
- _huayra_ 6y agoIt's a great language to learn as a gateway for language design, but I think what turns people off are unrealistic expectations. Haskell has warts, as do all languages. Something that's tedious in one language might be a breeze in another. In Haskell, most of the baggage I've seen is around - Cabal: seems the best advice is to just start with Stack - Delayed exceptions: due to lazy evaluation (which is a really great feature once you get used to it!), the site where you trigger an exception may not be anywhere near the actual exception-generating site. For example, if you call head on an empty list, then return that as a result only to have it be used far later, it will go "boom" at some later time. This is also true for I/O things: perhaps the file I/O way deep down in some thunk was closed due to an error, so some code that is not equipped to handle errors gets an exception. Michael Snoyman has a great series of blog posts about this [0], i.e. "Haskell the Bad Parts 1-3". Most of this is managed by not using some of the defaults or with practice. Just be aware that like any language, there will be areas that may not have the greatest behavior. That said, I think these confusing behaviors are very limited in Haskell, much more so than in C++ for instance. [0] https://www.snoyman.com/blog/ https://www.snoyman.com/blog/
- revskill 6y agoStack on windows is a nightmare :( Cabal is good, cross-platform really.
- travv0 6y agoWhat problems have you run into with Stack on Windows?
- cies 6y agoIf you are interested in learning Haskell, do not start with Snoyman's blogs. They are good, but not something a true beginner should be bothered with. I can recommend the https://haskellbook.com https://haskellbook.com as an introducing resource. If you want to dabble with something simpler/cleaner than Haskell, try Elm. It is just for browser apps, but extremely powerful and beginner friendly. You do not even have to install anything when you use this online tool: https://ellie-app.com/new https://ellie-app.com/new
- christiansakai 6y agoI wonder if I will ever use Haskell at all. Currently I'm trying to learn PureScript as the next closest thing I can use in production.
- johndoe42377 6y agoThis is a pretty bad writing compared to classic writers (Hudak, Hutton, Bird or Thompson). It begins with nix, which is a cancer (solving of non-existent problem by attention seeking narcissists - stable interfaces and semantic versioning will do). Then it proceeds with a subpar code, which mixes styles without justification, is cryptic and unreadable. You don't have to zip and then unwords, case is cryptic and redundant, etc. And it is not some rant, it is an adequate peer-review as it should be. Simplification (reduction) to perfection (when there is nothing more to remove) both in abstraction and in code, is not optimal with Haskell. Piling up of esoteric bullshit such as lenses and monad transformers is a non-goal. Xmonad, cabal and, of course, GHC itself are still the gold standard. No bullshit dependencies.
- tpoacher 6y agoSo then, why learn prolog?
- szopa 6y agoFor me the greatest benefit of learning Prolog was really understanding recursion – the only way to iterate through something is with a tail-recursive call. Also, it really makes you appreciate the For loop ;) Another cool aspect of Prolog is how simple it is to write a meta interpreter. Fort example, you can easily change Prolog's default depth first search through the solution space to breadth first, or iterative deepening: https://www.metalevel.at/acomip/ https://www.metalevel.at/acomip/
- agumonkey 6y agoProlog is kinda the natural step after FP. Now variables are not one point in space but the whole space itself. Combinatorial bliss. The syntax is kinda shorter.. Whether it's prolog, Kanren, datalog or any other relational language I wish everybody to enjoy the mind expanding effect. ps: for any scheme ready, 'the reasoned schemer' is a good book about the pieces for relprog
- Igelau 6y agoWell, in order to satisfactorily answer that, we'd have to agree on what constitutes a good reason... (describes a notation for propositional logic) Oh. I see what you did there.
- yowlingcat 6y agoI fondly remember my time learning Haskell in uni. Some of the most brain expanding stuff I did during that period. Of course, when the time came to actually use it to build my thesis work (data mining collaboration patterns in open source software), I fumbled around with Haskell for months trying to get something done, and then "in anger" wrote the whole thing in Python. I've since gone on to do most of my career in Python and haven't looked back. But something deep inside of me certainly misses Haskell. And try as I may to let old bygones be bygones, I keep trying to figure out a good use for it. I certainly wonder whether there's a niche for convex optimization problems where I'd otherwise use `cvxopt` in Python, or something in Julia, or even (if I was feeling particularly exotic), something in Prolog. Basically, what I'm trying to get at is whether there's something that Haskell's enormously powerful compiler could do so much better than other languages that it would be reason enough to write service code in it. Anyone more experienced in HS have thoughts on this? I know Facebook uses it in production.
- redcat7 6y agoI love academics. They can post shitty code full of single letter variables etc and still get the applause for it, not to mention the paycheck :D
- exdsq 6y agoRegarding this example, which variable could do with being longer? It seemed fine to me!
- segmondy 6y agoacademic is about computer science not computer programming. 2 very different things, their "shitty code" is often "good computer science code" and just like it's fine to have single letter variables when reading mathematics, it's the same when reading computer science code. the idea is to get knowledge across which can then be expressed clearly by computer programmers.
- redcat7 6y agoscrew this shit
- bidirectional 6y agoThis is not shitty code, single letter names have their place, and are absolutely fine here.
- mulberrybush 6y agoI like Golang's convention for names - names should get longer and more expressive the wider their use is across the code. Single letter names for loop variables, two or three letter names to refer to the current struct in methods, but expressive struct and function names.
- agumonkey 6y agoI'm trying to fiddle with python lambdas to make a timeout monad.. or something like that. Didn't have that much fun in a year. FP is confusing at first but really a strong source of fun.
- moralsupply 6y agoInterestingly Cardano Ada (a cryptocurrency, in case you don't know) if fully coded in Haskell and has been gaining a lot of traction recently -- it's now #3 cryptocurrency by market capitalization and might start competing with Ethereum for #2 during this year
- axilmar 6y agoI have only worked with Haskell on a personal basis, trying to understand if purity has any actual advantages. I have yet to be persuaded about the need to have code be pure. I never had any issue reasoning about impure code, and I do not find that the impure style has actually benefited me in any way. My logic bugs still continue to appear in pure code. What I really find annoying is when I have to update state. I always have to write tones of functions in order to re-synthesize the data after the smallest change, and the deeper the data model tree is the more functions are needed. Did I ever have any benefit from using the IO monad or the state monad? I don't know..it seems to be the number of bugs between my non-IO code and my IO code is roughly the same. Perhaps it shines on a collaborative level...I don't know, I never had the chance of writing Haskell code with other people.
- headbee 6y agoCode purity isn't just for you, it's also for the compiler to be able to make assumptions about the code in order to apply optimizations that would not otherwise be possible. For example, if the compiler "knows" that a certain branch won't be used, it doesn't have to evaluate it. This is part of the reason why Haskell can reach near-C performance and why its recursion is particularly performative.
- tome 6y ago> Code purity isn't just for you, it's also for the compiler to be able to make assumptions about the code in order to apply optimizations Yes, and purity is also for your collaborators (including your future self) who didn't write the code so don't understand it as well as you do.
- colllectorof 6y agoIt's funny how none of these posts about learning Haskell ever take a working program and demonstrate the benefits of the language by examining useful code.
- Igelau 6y agoThat wasn't the point of the article. I think you skipped to the punchline and missed the joke. More "useful" are examples are linked at the bottom, so I'm not sure what you're griping about unless you just don't like Haskell.
- blacktriangle 6y agoI'm probably way OT, but this seems like a decent place to get some opinions and this article doesn't address my issue: Here's my problem with Haskell: I want to model my domain as collections of heterogeneous maps. I work in the B2B world where our databases go back years but every week either the sales dept or our customers are throwing totally new requirements at us changing the way we think about our domain. We also do a ton of work with SQL which is trivial with such a mindset as relations are just sets of maps, but working with relations in Haskell, or any strongly typed language requires mapping layers that become their own source of unnecessary complexity. I love the idea of the compiler doing more work for me and really do miss the advantages of type systems for communicating intent to other developers. I've had positive experiences with C# in game dev and Scala in scientific computing, but in my current role shoving the real world into a typed box has been an exercise in futility. Am I missing something about Haskell that supports this world or is it just a bad fit for my org?
- thethimble 6y agoMaybe your domain can’t be modeled better than heterogenous maps. But Haskell’s type safety extends beyond your immediate domain. Writing a web server, interfacing to a database, etc. all have well formulated domains and Haskell’s type safety provides a lot of value there. Finally, I’m not denying that some domains are too chaotic and fast changing to be modeled statically. But there’s like some subset of your domain that is indeed static. Can you represent that statically and represent the other subset dynamically?
- blacktriangle 6y agoTrue, and that's where it feels like the Haskell side would be powerful. I did a small demo app with Yesod and loved it, and we have a ton of state machine type logic that would hugely benefit from ADTs. You're right the hybrid approach seems better, but there it seems more like that Python/Ruby with their new gradual typing seems like the way to go, adding strong on top of dynamic rather than trying to poke a hole in strong typing to let you be dynamic.
- travv0 6y ago
- bcheung 6y agoPersonally, I love Haskell and wish I can use it more. This article does not do justice convincing people to invest time to learn it. Is this like the curse of teaching monads? Once you know them you lose the ability to teach someone else about them? > If we sincerely ask "why learn Haskell?", then we wind up learning Haskell! No. We wind up doing a search for "Why learn Haskell" and unfortunately this article might pop up. And if we don't see a benefit or pain point being removed we aren't going to learn it. They don't even make an argument for why. They just jump into a philosophy lesson on logic. That's not an argument for learning Haskell and is completely tangential. The basic rules of copywriting requires that you understand your target audience and make a case for how their life will better. > The gold standard is a logical reason. LOL. No, it's not. The gold standard is an emotional reason. Perhaps this is why Haskell has not taken off. What pain point does it solve or what benefit does it give you? For me personally, it has expanded my thinking and allowed me to write clearer and more concise code in other languages. It has allowed me to think in terms of new concepts that increase the reach of what I am able to do. Its type system provides for safety as well as making the intent of programs clear. Pattern matching allows you to specify your intent much easier and conveniently than the typical imperative approach. The compiler is your friend and reminds you if you fail to take into account all possible scenarios (total function). The syntax may seem strange at first, but I have come to love it and wish other languages had adopted such a clean syntax devoid of visual clutter. The gold standard reason for me is that I am able to tackle, think, and solve higher levels of complexity than are possible in other languages. I am able to express myself much more fluidly and I am able to reuse code to a much higher degree.
- icrbow 6y ago> LOL. No, it's not. The gold standard is an emotional reason. Maybe the emotional reason is a warm fuzzy standard?
- sinkasapa 6y agoIf you don't care about engineering, and are in the humanities, philosophy or theoretical areas of the social sciences where you use logic, this article actually makes a great case for why you'd care about learning any programming language at all. They help you prove theorems. Haskell is a gateway drug to Coq or Lean. I don't know that someone who already programs a lot is the target audience for something like this.
- carapace 6y agoHaskell is a great language! (FWIW the argument in TFA also applies to Prolog: https://sforman.srht.site/source/TermsInProlog.html https://sforman.srht.site/source/TermsInProlog.html ) The problem I have with it is the meta-language. I tried Haskell a few weeks ago and "stack" installed over 27000 files. I feel like it's a case of "Physician heal thyself." Turn the power of Haskell back onto it's own tooling. (Python suffers from a similar problem, where distributing and installing Python code has been paradoxically un-Pythonic.) Some languages like Elm and Gleam distribute single binaries that you just put in your PATH.
- dwohnitmok 6y agoThis is my number 1 concern when it comes to writing larger Haskell programs. Its tooling is so meager compared to what it could be and should be were the promises of the languages fulfilled. Given how good Haskell is at writing compilers and code analysis tools it should have a best-in-class IDE, installation process, etc. when that is most definitely not the case. Luckily the past few years seems to have witnessed rapid improvement on this front so hopefully my gripe will be irrelevant in another few years.
- namelosw 6y ago'Why Learn Haskell?' is not a very hard question to answer nowadays since it's one of the most 'Perlis Language'. I hope there's one day we can answer 'Why Use Haskell?', and enjoy all the elegance and preciseness it has to offer. In reality, however, Haskell is the language that continuously and intentionally 'avoiding success'. Scala was the 'Haskell' in the engineering world a decade ago and still is. There was a trend of hosted languages like Scala and Clojure. It was a way to attract the audience because it was the de-facto platform. Nowadays this trend started to die out, and new generations are more on bare metal, like Rust and Go. It seems like there's a niche that looks like the new Scala while on bare metal, targeting engineers while without all the historical syntax.