17 ms·
I learned Haskell in just 15 years
- Loxicon 2y ago"It’s quite natural to program in Haskell by building a declarative model of your domain data, writing pure functions over that data, and interacting with the real world at the program’s boundaries. That’s my favorite way to work, Haskell or not." Are there any good resources you can share to learn this specific way of programming?
- tome 2y agohttps://pragprog.com/titles/swdddf/domain-modeling-made-functional/ https://pragprog.com/titles/swdddf/domain-modeling-made-func..., even though it's F# rather than Haskell. And maybe https://leanpub.com/algebra-driven-design https://leanpub.com/algebra-driven-design depending on the exact use case.
- munchler 2y agoCute. All kidding aside, though, functional programming is worth the effort to learn, and it doesn't actually take 15 years. The payoff is at the end of the article: "It’s quite natural to program in Haskell by building a declarative model of your domain data, writing pure functions over that data, and interacting with the real world at the program’s boundaries. That’s my favorite way to work, Haskell or not." Haskell can be intimidating, though, so I would recommend F# for most beginners. It supports OOP and doesn't require every single function to be pure, so the learning curve is less intense, but you end up absorbing the same lesson as above.
- initplus 2y agoYes - the value of functional programming isn't that working in OCAML, or F#, or Haskell is 10x as productive as other languages. But that it can teach you worthwhile lessens about designing software that apply equally to imperative languages. Modelling the business domain, reasoning and managing side effects, avoiding common imperative bugs, these are all valuable skills to develop. F# is a great language to learn, and very approachable. Worst part about it is interacting with antiquated .NET API's. (I can't believe the state that .NET support for common serialization formats is still in...)
- sidkshatriya 2y ago> Yes - the value of functional programming isn't that working in OCAML, or F#, or Haskell is 10x as productive as other languages. This is not true in my personal experience. As has been famously said (paraphrased): Functional programming makes tough problems easy and easy problems tough. In other words the value of functional programming depends on your domain.
- NinoScript 2y agoSo you’re saying that it does make you 10x as productive?
- initplus 2y agoMaybe my phrasing is not clear - I meant that these languages are indeed not significantly more productive.
- marcosdumay 2y agoBut (and I agree with the GP) they are. They are overwhelmingly more productive, in a way that you often can't even compare quantitatively. They are also a lot less productive. It depends entirely on what you are doing.
- grumpyprole 2y agoBy what measure? Haskell can be a huge productivity multiplier. The standard library is built upon many powerful, unifying and consistent mathematical abstractions. For example, there is almost no boilerplate to write for any traversal, mapping, error handling etc. The average Pythonista simply has no idea what they are missing. But Haskell doesn't have anywhere near the third party ecosystem of Python, so is less productive by some measures.
- antonvs 2y ago> easy problems tough. That needs a qualifier: it can make easy problems tough if you're not familiar with how to solve them in a functional context. A big part of that is because smart people have already solved the tough problems and made them available as language features or libraries.
- nequo 2y agoThat’s interesting because F#’s OOP, as someone who knows neither C# nor Java, makes it more intimidating to me than OCaml. Also interesting that when FP is mentioned, Hindley-Milner is implicitly understood to be part of FP too even though it doesn’t have to be. Clojure emphasizes immutability and FP but with dynamic typing and everything that comes with that.
- mrkeen 2y ago> Clojure emphasizes immutability Is "emphasizes" just another word for second-class support? C++ emphasizes the importance of memory safety.
- y1n0 2y agoImmutability is definitely first class in clojure, but you can work with mutable structures when you need to.
- mrkeen 2y agoThis is sounds like memory safety in C++. https://www.infoworld.com/article/3714401/c-plus-plus-creator-rebuts-white-house-warning.html https://www.infoworld.com/article/3714401/c-plus-plus-creato...
- nequo 2y agoThis seems like a meaningless criticism when it comes to immutability in Clojure. You can have mutability in Haskell too. That doesn’t make it as unsafe as memory management in C++.
- mrkeen 2y ago> You can have mutability in Haskell too. Haskell enforces this via a type system. What safeguards around mutability does Clojure have? If I import a method 'foo()', is there any kind of contract, notation ... anything which could suggest whether it mutates or not?
- __rito__ 2y agoFor the benefit(s) that you list, which are the best learning resources for F#?
- neonsunset 2y agohttps://fsharpforfunandprofit.com/ https://fsharpforfunandprofit.com/
- richrichie 2y agoBut why do we need Haskell for this?
- anon291 2y agoRealistically we don't but it's very rare to meet a programmer who understands these distinctions thats not also a great functional programmer. This is my experience after spending five years as a Haskell programmer and managing a Haskell team for several years and now moving back to the c++ world to play with AI. I know lots of good c++ programmers working on cutting edge stuff, real experts in their field, but they sometimes still don't have a clear way to understand how to model data That is my opinion. It's probably highly contentious.
- cornel_io 2y agoI've actually had to fire a technically exceptional Haskell programmer because of the damage they did to our C# codebase (and arguably moreso, the team). Sometimes it's not a matter of talent or skill, but culture fit. In my experience FP-aligned people on non-FP projects tend to be more likely to overengineer, more prone to argue in favor of the Great Rewrite For No Reason Except Aesthetics, and more likely to abuse "lesser" programmers when they put up PRs. They suck as team players on teams that are not made of language nerds. I am not just talking about the one person here who I fired, this is a legit pattern I've noticed over at least a half dozen people. Conversely, they are exactly the right people to deploy when you have really tough, self-contained problems to solve that you wouldn't trust the normal Java 9-5ers to tackle. No matter how they do it, you can always rewrite their working code in a more maintainable language later once it's working, and make it integrate well with the rest of your stack. :D
- MrBuddyCasino 2y agoThis is my experience, too. Some of the worst code I‘ve seen was a Haskell guy who first built his own (reactive?) concurrency framework and then implemented the actual functionality in completely unidiomatic and undocumented Java. Some people don’t understand that the „best solution“ is not necessarily equal to the most beautiful abstraction they can think of.
- beders 2y agoI feel the same pay-off - but arrived at that point via Clojure. Immutable-first, aim for purity, ability to drop out of it when necessary. As stringent as you need it to be (static vs. dynamic types vs. specs), as flexible as you want it to be.
- IshKebab 2y agoI feel like functional programming is pretty trivial. It's pure programming that is very difficult. They're often conflated because Haskell is pure and functional and probably the most talked about heavily functional language. I certainly didn't know that impure functional languages like OCaml existed for ages.
- fire_lake 2y agoIs Haskell pure? It has exceptions You can divide by zero It has unsafe IO primitives
- tome 2y agoYou're right: "pure" is not a well-defined concept. The well-defined concept that describes Haskell's benefits in this regard is "referential transparency". That means that this code let x = <definition of x> in ... x ... x ... (i.e. defining a variable x and then using it some number of times) is equivalent to ... <definition of x> ... <definition of x> ... Seen in the opposite direction (transforming the bottom code to the top code) this means that extracting repeated code is always a valid thing to do. It's not valid in most other languages, and certainly no mainstream ones.
- simiones 2y agoWell, technically that isn't true if you use, for example, unsafePerfomIO in the defintion of x. Referential transparency is still a spectrum, just like purity. Haskell is much closer to purity than the vast majority of languages out there. Also, even if Haskell were perfectly pure, the fact that it uses lazy evaluation is far more important to actually being able to make use of referential transparency. In a strict language you will still see a massive performance differences if replacing the first version with the second, in the most common cases.
- tome 2y ago> technically that isn't true if you use, for example, unsafePerfomIO in the defintion of x Ah, well, regardless of whether it holds in Haskell, referential transparency is a well-defined concept. Purity is not a well-defined concept (at least as far as I know. Please share a formal definition if you have one!). That's primarily what I'm trying to say. But I also disagree with your point about unsafePerformIO. In practice, nothing in Haskell violates referential transparency in a significant way. Who knows why? It's an emergent phenomenon that in principle need not have occurred, but in practice it did. Debug.Trace and similar are about the only things that technically violate referential transparency (and they are extremely tame). > the fact that it uses lazy evaluation is far more important to actually being able to make use of referential transparency Yes, I agree with that.
- realPtolemy 2y agoOr Elixir! Quite easy to grasp as well.
- dejvid123 2y agoI would suggest Scala as FP for beginners. It doesnt forces you to do pure functions. And its really beginners friendly to start with.
- empath75 2y agoI was a college dropout and self taught bash and python programmer and quite some time ago, I read about Haskell, decided to teach myself to use it, and then realized I had absolutely no idea what programming actually was, and basically spent the next 15 years teaching myself computer science, category theory, abstract algebra and so on, so that I could finally understand Haskell code. I still don't understand Haskell, but it did help me learn Rust when I decided to learn that. And I think I could explain what a monad is. edit: It's a data structure that implements flat map. Hope this saves someone else a few years of their life.
- bspammer 2y agoI think that's a good starting definition for programmers, but still could cause confusion when you run into something like IO in Haskell. IO isn't really a data structure, and it's hard to fit the "flat map" concept to it.
- nextaccountic 2y agoIf you want you can still keep this point of view, by saying that IO is conceptually a data structure that builds a description of what the program does. In this point of view it follows that there is another, impure program that interprets the IO data structure and actually performs the computations (Of course in practice IO isn't implemented like this, because it would be too slow) (But in every other language, like Javascript or Python, you can define IO as a data structure. Or even in Haskell itself, you can define for eg. a free monad that gets interpreted later, and it can be made to be just as good as IO itself, though typically people make it less powerful than IO) However note that every other "computational" monad (like the list monad or the Cont monad) actually is a data structure, even though they describe effects just like IO does. This is because IO is the only possible exception to the "monads are data structures" thing in Haskell (if you don't subscribe to the above view), because Haskell doesn't let you define types that aren't data structures The only issue with this point of view is that you now need to say what flatMap means for things that are not shaped like arrays. Eg. does it make intuitive sense to flatMap a tree? (A retort is that it must make sense, whatever you call this operation; and flattening a tree means to turn a tree of trees into an one-level tree)
- crabbone 2y agoI would recommend neither of those. Haskell has very bad syntax (with extensive backing from Microsoft, iirc the guy who writes the compiler is a Microsoft's Research employee). F# is a straight-up Microsoft's language. It doesn't matter what other benefits it has. Just don't touch anything created by that company, and you will have one fewer regrets in your life. But, if you still want a language from that category: SML or Erlang would be my pick.
- fransje26 2y ago> Just don't touch anything created by that company, and you will have one fewer regrets in your life. :-)
- square_usual 2y agoSPJ has left MSR and is now at Epic games, working on a new PL. However, even while he was at MSR, MS didn't really have a say in how Haskell was developed.
- crabbone 2y agoWell, MS didn't have to do anything. It's enough that they have (or had) the opportunity to do something. There isn't an Overmind in MS that in a creepy voice tells you to spawn more overlords. Less than that, there doesn't need to be a written document that tells you to give money to MS or your data etc. There's just a general accepted understanding among the people who run that company that ends justify the means. And by "ends" they mean them and their investors getting rich. If Haskell compiler could've been turned into a money-making machine, and it only required killing off half of Haskell programmer, MS would be working overtime on the plan to hide the bodies, but they'd never even consider the possibility of killing being bad... (metaphorically speaking, hopefully)
- nequo 2y agoDo you also suspect homicidal money making motives behind Z3, Lean, and F*? It seems more likely to me that they just want some useful knowledge out of these projects that they can integrate into a product that actually sells.
- czhu12 2y ago> doesn't require every single function to be pure having never done F# or haskell, doesn't that start getting into the territory of languages that encourage functional programming like ruby or javascript (modern javascript)?
- Bostonian 2y agoIn modern Fortran, functions should be pure (although the language does not require this), and procedures that mutate arguments are made subroutines (which do not have return values).
- pklausler 2y agoNote that Fortran's interpretation of the term "pure" bizarrely allows a "pure" subprogram to depend on mutable state elsewhere (in a host, a module, or a COMMON block). So Fortran's "pure" functions aren't referentially transparent. (F'2023 added a stronger form of "pure" and calls it "simple", but it didn't strengthen the places where a "pure" procedure should be required to be "simple", such as DO CONCURRENT, so being "simple" will be its own reward, if any compiler actually implements it. And a "simple" function's result value can still depend on a mutable pointer target.)
- sterlind 2y agoI really wanted to like F#, and I kinda do, but it has a number of quirks, compiler issues and cracks in the design that are getting worse: First off, the compiler is single-pass. All your definitions have to be in order. This even extends to type hints - it can't use clues to the right to deduce the type of an expression on the left. This is supposedly for perf reasons, but the compiler can become extremely slow because the inference engine has to work so hard - slower than GHC for sure. Speaking of slowness, Haskell is surprisingly fast. Idiomatic Haskell can be within 50% the perf of C, since its laziness and purity unlock powerful optimizations. F# is eager and the compiler doesn't do anything fancy. Perf often makes you reach for mutable state and imperative structure, which is disappointing. The OOP paradigm feels bolted on. Should you use classes or modules? Pure functions or members? It depends, what mood are you in? Unfortunately only member functions support overloads, and overloads are useful for some SFINAE-type patterns with `inline` functions, so they get a bit overused. `ref` struct support, which is vital for zero-copy and efficient immutable data, have very primitive support. even C# is ahead on this. Very limited support for implicit conversions, no support for type classes and no function overloading leaves F# with nothing like a numeric tower you'd have in Lisp, and makes building something like Numpy clunky. I use C# at work, and I love Haskell, so I really wanted to love F#. But it just doesn't get the love it needs from MS, and some design decisions aren't aging well - particularly as C# itself evolves in directions that are tricky for F#'s aging compiler to support.
- stoorafa 2y agoHad a lot of fun reading this. I’d love to see some of the author’s code to get a sense what the journey produced, if that’s even possible
- iso8859-1 2y agohttps://github.com/esilverm https://github.com/esilverm
- colejhudson 2y ago[flagged]
- TrackerFF 2y agoWhat's the benefit of learning a PURE functional programming language, opposed to just using a language which has adapted the best bits and pieces from the functional programming paradigm? Given that you want write code that sees "real world" use, and is used to handle data and events from the real world. To me, sometimes the line between optimized code and intellectual curiosity blurs.
- mrkeen 2y agoThis is all myth. People don't write Haskell, because they read why other non-Haskellers also don't write Haskell, based on what other non-Haskellers wrote. > a language which has adapted the best bits and pieces from the functional programming paradigm? Why write in a statically-typed language when dynamically-typed languages have adapted the best bits and pieces from statically-typed languages?
- cosmic_quanta 2y ago> Why write in a statically-typed language when dynamically-typed languages have adapted the best bits and pieces from statically-typed languages? Unfortunately, dynamically-typed languages haven't adapted the best bit from statically-typed languages: that all types are enforced at compile-time!
- mrkeen 2y agoYep, that's the parallel I was going for. Functional languages give you the same output for the same input, and almost-functional languages ... probably give you the same output for the same input?
- Skinney 2y ago> What's the benefit of learning a PURE functional programming language 1. It makes it easy to learn how to structure a program in a pure way, which is hard to do in languages that offers you a easy way out. 2. Since "everything" is pure, writing tests is easier. 3. You know for certain that if you discard the result of a function call, all the side-effects that it would normally trigger would be stopped as well. 4. A program where all side-effects are guaranteed to be pushed to the boundaries, is a program that's easy to reason about. > a language which has adapted the best bits and pieces [...] Languages that has adapted to best bits and pieces from X, Y, Z tend to be worse than a language specifically for X, Y and Z. For instance, Java supports functional programming but functional programming languages are much better at it because they were designed for that specific paradigm. In the same vein, sure you can write pure programs in F#, but not as easily as in Haskell that was designed for doing just that. > and is used to handle data and events from the real world Pure code really only means (in practice) that side-effects are controlled, which is generally very helpful. It forces you to structure programs in a way which makes it easy to pinpoint where data is coming in, and where data is going out. It also makes for easier testing. Being able to know, definetly, the answer to "will calling foo perform a network request" without having to read the source for foo is quite nice, especially when dealing with third-party code. All this said, I probably wouldn't begin with Haskell. A language like Elm is much better suited for learning writing pure programs.
- leononame 2y agoGreat read! Can anyone here recommend a good resource for learning Haskell that's in the style of "Text-Mode Games as First Haskell Projects"? Haskell has been on my radar since forever, and I've got some FP concepts internalized by making a side project in F#, but I have no idea what a monad really is and a fun prohect to code along might be perfect.
- brabel 2y agoI've been learning Unison [1] and I highly recommend. It's a Haskell-like language, but with some really interesting ideas around how code should be managed and distributed. They also use use algebraic effects (represented with "abilities" in Unison) instead of Monads, which gives some interesting advantages [2]. [1] https://www.unison-lang.org/ https://www.unison-lang.org/ [2] https://www.unison-lang.org/docs/fundamentals/abilities/for-monadically-inclined/ https://www.unison-lang.org/docs/fundamentals/abilities/for-...
- tasuki 2y agoHave you written anything in Unison yet? To me Unison feels extremely ahead of its time. They clearly thought things through and aren't afraid to challenge the status quo. Maybe a bit too much ahead of its time even... I fear `ucm` a little. You mean I can't version my things with git? How do I... ehh, do anything? And how is the deployment story if one chooses not to use the Unison cloud?
- carbonatom 2y agoCan you or someone else familiar with Unison tell us what specific things about Unison feel ahead of its time? I don't know Unison so these things will be a good motivation for me to learn Unison.
- cflewis 2y agoUnison tries to swallow the whole elephant all at once, which is probably what the author is getting at. * `ucm` is like a coding assistant that sits with you the whole time. You don't grep through code to find snippets or anything, you use `ucm`. It does a whole lot more, but that's just the trivial example. * You need `ucm` because Unison stores code as a syntax tree, not text. This is awesome because versioning/dependency conflicts/rename issues just go away. This is not awesome because nothing else knows how to understand this: other source control systems will just not work. * It's really trying to drag functional coding into this decade and what we use code for in production. It's not trying to be Haskell which is a great language, but doesn't (to me) feel like it was designed to do something like a simple web app. * It is supposed to do distributed cloud computing without modification (this smells like where the VC money came from), but again, you have to use their platform because other clouds don't understand Unison. The list goes on. Each individual piece of Unison I think is really great. I love the `ucm` model of having an assistant sit next to you the whole time. What I don't love is that there is just _so much_ learning placed on the developer. To understand Unison, you need to understand a lot of what they're doing, a lot of what they are doing is novel, and so you have to eat the whole elephant that they are. I don't know if there was a path where they could have eaten the elephant one bite at a time, but it really makes the onboarding onerous.
- neonate 2y agohttps://web.archive.org/web/20240617035104/https://duckrabbit.tech/articles/learning-haskell.html https://web.archive.org/web/20240617035104/https://duckrabbi...
- drwu 2y agoWhen Haskell was a hot topic around two decades ago, ML was also quite often discussed. Today ML almost only means machine learning
- firesteelrain 2y agoThat's what I remember from my Computer Science classes 2001-2002. Standard ML was hard to learn back then for a newbie especially a Computer Science newbie.
- dboreham 2y agoML exists today as OCaml and F#
- iNic 2y agohttps://archive.ph/gqOsY https://archive.ph/gqOsY
- usgroup 2y agoIn my opinion, if you are after the mystical experience of understanding functional programming, you're better off learning Prolog. I think it has more to offer in terms of insight, because wrapping your head around the language only takes a couple days, but wrapping your head around its consequences is a gift which keeps on giving for quite some time. Immutable functional programming is basically what 80% of your Prolog code will look like. The benefit is that you'll be able to understand how everything works from end-to-end.
- Valodim 2y agoProlog is a logic programming language though, I wouldn't expect it to have a lot of overlap with functional programming?
- usgroup 2y agoProlog variables are immutable by default. Data structures are the same as the immutable functional programming counterparts (no arrays, and tree based everything). Recursion is the only way to loop. Map, filter, fold(l/r), reduce, accumulate, etc, are staple predicates. As I said, 80% of your code, or more, will look just like a functional programme.
- cess11 2y agoAn execution pipeline in a functional language is just half a relation in Prolog. Prolog allows you to also run it 'backwards', you can provide the output and have it figure out what the inputs would need to be.
- usgroup 2y agoRun in backwards, so they say, but not really. Most things you'll write can't run backwards. You have to write them in a special way for that to be possible, and even then what it means is that you can do a depth first search to find the value. There are some useful extensions like clpfd and asp but really if what you're doing is solving a constraint programming problem, you're much better of with OR-tools or MiniZinc. Prolog is beautiful. I have practically no use for it. I've struggled to find something I can do better with Prolog than other tools, but I just love it aesthetically and that's enough for me sometimes.
- tomcam 2y agoSure, lord it over the rest of us peons. We can’t all be overachievers, you know.
- revskill 2y agoYes, it's better to spend 15 years to learn Haskell than keep creating messy imperative programs without knowing how to improve.
- lonk 2y agoJust "15 years" or Nothing
- LittleOtter 2y ago"What fascinated me about Haskell when I was still a teenager? Who knows. I had been coding with increasing enthusiasm since I was 10 or 11 but I was no wunderkind. I certainly hadn’t attained anything like the skill or, more importantly, taste I had after just a few years in the working world. What I like about it today is that it’s quite natural to program in Haskell by building a declarative model of your domain data, writing pure functions over that data, and interacting with the real world at the program’s boundaries. That’s my favorite way to work, Haskell or not." I adore these sentences.:)When I read it,it feels like I met myself.