Monads are a Class of Hard Drugs (2008)
lambda-diode.com
Monads are a Class of Hard Drugs (2008)
1–10 of 37 posts
Re: Monads are a Class of Hard Drugs (2008)
#2Sure, they are used for state and IO, but they can do far more, like nondeterministic programming, continuations or even nothing at all. Ultimately, I would say monads are about composition: they let you define exactly how to compose computations.
Additionally, monads do not break type inference. Having a type for every top-label binding is considered good style in Haskell, but it is still optional. I could see this practice being confused for type inference not working. There are of course language extensions that do break type inference in certain cases, and sometimes it is impossible even with the standard language, but it works almost all of the time even with monads.
Also, and this is probably just because this article is for years old, it really overstates hire bad Haskell performance is. In my experience, even naively written code runs relatively fast--certainly fast enough for me--in most cases. I believe this has really improved in recent times. Haskell is certainly better in this regard than most other high-level languages.
Re: Monads are a Class of Hard Drugs (2008)
#3> The essence of monads is to use abstract types to enclose a mutable state [...]
This is a common misconception, but terribly misleading. The "essence" of monads are the bind and return (or equivalent) functions, allowing decoupled transformations to be performed. The fact that you can write bind and return functions for a type that encapsulates the idea of a side effect is secondary.
Would you say "the essence of iterators is to encapsulate infinite sequences"? Infinite sequences happen to be iterable, but to say that they are the essence of iterators is downright wrong. The essence of iterators is traveling through a collection item by item, as defined by the MoveNext/Current (or equivalent) functions.
> For one thing, when you use a monad, you get hooked to it: the type constructors of the monad start to appear in the signatures of your function.
If you have functions that should have nothing to do with a monad ending up coupled to it, then you're probably doing it wrong. Monadic methods let you "lift" functions, so they don't have to be coupled:
// bad: unnecessarily coupling your function to a monad
IEnumerable Increment(IEnumerable sequence) {
var r = new List();
foreach (var e in sequence) r.Add(e + 1);
return r;
}
...
var incrementedList = Increment(list);
// good: using monad method to lift a non-coupled function
int Increment(int b) { return b + 1; }
var incrementedList = list.Map(Increment);Re: Monads are a Class of Hard Drugs (2008)
#4This article is flawed at its core: monads do not, in general, compromise type inference and they are not all about sequencing state. Sure, they are used for state and IO, but they can do far more, like nondeterministic programming, continuations or even nothing at all. Ultimately, I would say monads are about composition: they let you define exactly how to compose computations. Additionally, monads do not break type…
---
And yeah, monads are much more about a particular type of composition or sequencing. Compare the common composition types (warning, scary but harmless jargon to follow)
class Monoid m where
e :: m
() :: m -> m -> m
class Functor f => Applicative f where
pure :: a -> f a
ap :: f (a -> b) -> f a -> f b
class Functor f => Monoidal f where -- isomorphic to Applicative
unit :: f ()
prod :: (f a, f b) -> f (a, b)
class Applicative m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
class Applicative m => Monad' m where -- isomorphic to Monad
return :: a -> m a
bind :: m a -> (a -> m b) -> m b
class Profunctor f => Arrow f where
arr :: (a -> b) -> f a b
(>>>) :: f a b -> f b c -> f a c
-- kind of ignore this one :)
first :: f a b -> f (a, c) (b, c)
You can see a progression in the constraints on how things combine as you move down the list. First you have plain composition of non-container Functor types.Then you have the Applicative/Monoidal functors (they're equivalent/isomorphic) which are probably most clearly demonstrated by the Monoidal class--it implements composition of Functors which maps to products in the contained types (or, has a "applicative" product which commutes with the functor)!
Then you have Monadic functor composition where you have "sequential" or "inward" composition via join (compare to Applicative's "horizontal" product composition) which can be implemented by the 'bind' function which maps a function that rewraps contained values.
Finally you have the Arrow types which add composition to Profunctors (which are like functors which contain both "incoming" and "outgoing" values) by composing them like a category.
---
Which is a lot of words to say that (1) Monads are just one of a whole group of "kinds" of composition and (2) they basically represent composition which allows for control over how functorial contexts get sequenced.
Re: Monads are a Class of Hard Drugs (2008)
#5This article is flawed at its core: monads do not, in general, compromise type inference and they are not all about sequencing state. Sure, they are used for state and IO, but they can do far more, like nondeterministic programming, continuations or even nothing at all. Ultimately, I would say monads are about composition: they let you define exactly how to compose computations. Additionally, monads do not break type…
How do you make Haskell code faster? Apparently it's somewhat like writing fast Java code: avoid most features, use primitive data types, and write like you're writing C. Haskell code optimized for performance ends up like messy C code more often than not, except that unsafePerformIO isn't such a prickly topic in C.
Even Haskell professionals often don't know when "free" GHC optimizations will kick in, because the optimizations can be so picky, even after you remember to apply some forgotten language pragma. Writing performant Haskell is a black art.
Re: Monads are a Class of Hard Drugs (2008)
#6Two glaring errors in here: > The essence of monads is to use abstract types to enclose a mutable state [...] This is a common misconception, but terribly misleading. The "essence" of monads are the bind and return (or equivalent) functions, allowing decoupled transformations to be performed. The fact that you can write bind and return functions for a type that encapsulates the idea of a side effect is secondary. Wou…
> But mutable state covers everything that is not pure computation and that includes debug statements, input and output, system calls, network access, getting the time of the day or even throwing an exception. So the monad you are using has to provide all these services. Of course not every monad has everything you need so you have the IO monad, the Maybe monad, the STM monad, and so on. Whenever you have a C binding, you get a monad.
The second point example doesn't seem to address the author's concerns. The author is complaining about what happens when you try to compose N components that all disagree on the model of computation. OCaml has a more practical default model of computation so less such plumbing is needed.
Re: Monads are a Class of Hard Drugs (2008)
#7This article is flawed at its core: monads do not, in general, compromise type inference and they are not all about sequencing state. Sure, they are used for state and IO, but they can do far more, like nondeterministic programming, continuations or even nothing at all. Ultimately, I would say monads are about composition: they let you define exactly how to compose computations. Additionally, monads do not break type…
It's probably true that simply written Haskell code is fast enough for most uses. The trouble comes when that code isn't fast enough, or should be faster. How do you make Haskell code faster? Apparently it's somewhat like writing fast Java code: avoid most features, use primitive data types, and write like you're writing C. Haskell code optimized for performance ends up like messy C code more often than not, except t…
Writing exceptional, highly performant Haskell is still a black art, sure. But writing performant Haskell is basically writing Haskell with a modicum of knowledge and respect (less lazy IO, more ByteString, more iteratees, etc). Writing highly performant Haskell is becoming easier and easier; the runtime system will give you detailed statistics about where your problems may lie, tools like ThreadScope can give you all the information you'd ever want, and many of the commonly-used libraries are heavily optimized for speed (Text, ByteString, iteratees, etc) which you benefit from basically for free.
It's not a panacea but I haven't ever had to use anything more sophisticated than strictness annotations, and even that I use pretty sparingly. Like the best black arts, it's very seldom necessary, and becoming more seldom every day.
As a side note, I would love to see an alternative "honest" shootout where programs must not do much overt "doping" (such as using Foreign and `unsafePerformIO`) because it would be interesting to compare the "native" speeds of different languages, with the kind of code the best normal people would write for themselves or their employer. Haskell has always abused its low-level facilities for higher placement in the shootout than it really deserves.
Re: Monads are a Class of Hard Drugs (2008)
#8I'm still looking for someone who can present a cogent explanation of monads using only Python.
(I'm willing to replace "Python" in the above challenge with "any language I know well," which would include Python, C, C++, Java, JavaScript, and quite a few others which I won't bother to list here. Notably lacking from this list are Lisp, Scheme, Caml, Haskell, Prolog, Erlang, and most other languages whose view of the world is "weird." NB not that I'm against learning such languages; it's more a matter of available tutorials and time.)
Re: Monads are a Class of Hard Drugs (2008)
#9Anyone who understands monads is on a class of hard drugs. I'm still looking for someone who can present a cogent explanation of monads using only Python. (I'm willing to replace "Python" in the above challenge with "any language I know well," which would include Python, C, C++, Java, JavaScript, and quite a few others which I won't bother to list here. Notably lacking from this list are Lisp, Scheme, Caml, Haskell,…
+ the List monad (probably the easiest for python people, since it's very similar to list comprehensions)
+ the Maybe monad (kind of a degenerate case)
+ the State monad
And it's much easier if you do it in Haskell, trust me. "Learn You A Haskell For Great Good" is a nice easy intro to the basics.
Re: Monads are a Class of Hard Drugs (2008)
#10Anyone who understands monads is on a class of hard drugs. I'm still looking for someone who can present a cogent explanation of monads using only Python. (I'm willing to replace "Python" in the above challenge with "any language I know well," which would include Python, C, C++, Java, JavaScript, and quite a few others which I won't bother to list here. Notably lacking from this list are Lisp, Scheme, Caml, Haskell,…
It's so frustrating to hear you say that. Monads are such a simple concept but they're difficult to explain because they're far more general and abstract than most programming topics. The best explanation I have is that monads are a way of storing some kind of computation with a value. When the user wants access to that value, he uses a monadic operator which forces the monad's computation to be run before returning the value.