7 ms·
This would be a reasonable critique except that monads are really why Haskell ends up being so powerful and composable. Sure, they can be tough to wrap your hea
by devishard 10y ago
This would be a reasonable critique except that monads are really why Haskell ends up being so powerful and composable. Sure, they can be tough to wrap your head around, but without them Haskell wouldn't be particularly special or useful.
- pron 10y agoIt's more complicated than that. Monads don't make a language more powerful, but they are an absolute necessity given Haskell's design, which is built around extensional/value semantics, which basically approximates a program/subroutine as the function it computes; this is a useful approximation as it lets us treat computations as if they were referentially transparent. That approximation has a cost, though, as computations are not quite functions (they are processes that compute functions), and while the approximation works well enough much of the time, some things require recapturing the more accurate definition of computations as continuations (i.e. a computation can block and then resume). If your language does not have continuations, only functions, monads achieve the same thing. If, OTOH, your language has continuations (as most non-pure languages do, although most don't have reified continuations, which are just as "programmable" as monads only more composable), monads don't really help. See http://blog.paralleluniverse.co/2015/08/07/scoped-continuations/ http://blog.paralleluniverse.co/2015/08/07/scoped-continuati...
- Peaker 10y agoIt's not really Monads making the language more powerful. It's the taking away of non-pure primitives and libraries -- and replacing those with type-labeled effects. That these effects are composed monadically is a minor detail and unfortunately the thing that's emphasized. Haskell gains power in its framework for restricting code. In Haskell, you can know so much about what code doesn't do -- and that's what makes Haskell special and powerful compared to other languages. You have to explicitly opt out of these restrictions - making the majority of code easier to reason about, simply because there is so much it cannot do.
- pron 10y ago> It's the taking away of non-pure primitives and libraries -- and replacing those with type-labeled effects. PFP and typing are quite orthogonal. You can have effect systems in non-PFP, continuation-based languages (i.e. languages that don't equate computations with functions). You can have non-pure, non-monad-based type-labeled effects. > Haskell gains power in its framework for restricting code. Sure, but Haskell does this within a very specific design, based on extensional functional semantics. There are other ways of restricting what code can or cannot do that don't have the same semantics. Personally, I think that various effect systems may hold promise and are certainly interesting enough to try, but the PFP abstraction has so far failed to yield results commensurate with its cost.
- Peaker 10y ago> PFP and typing are quite orthogonal They are orthogonal in 1 technical sense. But the benefits are reaped from the combination. > the PFP abstraction has so far failed to yield results commensurate with its cost. You say this based on what? Me and other Haskell users believe that the costs are very minimal and the benefits are quite huge.
- pron 10y ago> But the benefits are reaped from the combination. Well, I happen to think that some forms of rich typing are quite beneficial, but that value-semantics is a negative. I don't see Haskell having any tangible benefits whatsoever over, say, OCaml (other than ecosystem-related stuff), which has one (relatively rich typing) but not the other (PFP). > You say this based on what? Based on the fact that the few Haskell shops out there -- despite them being composed of avid enthusiasts and people who devote a lot of thought into the Haskell way of thinking, are not reporting even 2x productivity gains (although I don't know what huge means to you). I mean, some say they feel those gains, but when you look at iteration speed, time to market etc., you see negligible advantage if at all. As to the cost, I won't argue with you, but I encourage people who are interested in languages as well as in software engineering to try Haskell and judge for themselves.
- tome 10y ago> Haskell's design, which is built around extensional/value semantics, which basically approximates a program/subroutine as the function it computes; this is a useful approximation as it lets us treat computations as if they were referentially transparent. That approximation has a cost, though, as computations are not quite functions (they are processes that compute functions) This sounds "not even wrong" to me. Care to explain in more detail? > If, OTOH, your language has continuations ... monads don't really help. Haskell has continuations. Your move.
- pron 10y ago> Care to explain in more detail? What exactly is unclear? In Haskell, a subroutine or a subprogram is modeled as a mathematical function. Programs are not exactly functions[1] but continuations (i.e., they are a process which can be paused and resumed). There's absolutely nothing wrong with abstracting computations as functions (and there's much to be gained, which is why programmers are encouraged to write pure functions where possible, regardless of the language they're using), but sometimes you need to use their continuation-quality, and that's when you need monads. > Haskell has continuations. Your move. No, it doesn't. It models continuations as monads which is precisely my point. If Haskell subroutines were continuations, it wouldn't need monads, just as OCaml doesn't. [1]: If they were, then computations would be extensionally equivalent like functions, but they're not: an observer can tell if you're running bubble sort or merge sort, even though they're computing the same function (which is why type theory introduces has the concept of definitional equality). A lambda term or a Turing machine are not functions but continuations; you can start reducing a lambda term (or running a TM), block it (i.e. capture the reduced term/TM state), and then resume it.