Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You can,

   h :: a -> IO [c]
   h = liftM g . f
Or fmap, or use various arrow operators, or <$>. I might describe it as “pathologically easy” to compose functions in Haskell, since it’s so much easier in Haskell than other languages (and mixing monads & pure code is still very easy).


Sure, but that's not a feature of Monads themselves, but a feature of the excellent generic programming support in Haskell, along with polymorphic return types that makes the boilerplate really easy.

Still, there is a slight bit more to the story if you actually had to pass a [c] to another function ( you would have to liftM that function as well, I believe, and so on for every function in a chain).


So I don’t think that this criticism is quite fair, and I’ll explain why. When you choose to make something implicit/easy in a language, it often comes with the cost of making other things explicit/hard. The best example of this, in my mind, is the choice to use Hindley-Milner style type inference (ML, Haskell) versus forward-only type inference (C, Java). HM style type inference comes with its advantages, but introduces limitations that affect polymorphism.

In Haskell, you can’t automatically lift something into a Monad because this would require a type of ad-hoc polymorphism that is impossible with a coherent Hindley-Milner type of type inference system.

However, that exact type inference system is what lets you just write “liftM”, and it automatically does the Right Thing based on the type of monad expected at the call site.

I think ultimately—Haskell is in a sense an experiment to see if these alternative tradeoffs are viable, and it’s a massive success in that regard.

(Also: you wouldn’t need to liftM every function in a chain. Just liftM the chain at the end.)


> Sure, but that's not a feature of Monads themselves, but a feature of the excellent generic programming support in Haskell

This easiness comes from the existence of fmap, which is defined for any functor (monads are all functors). To instance it and get haskell's lovely syntax, any given "container" has to define its own fmap implementation. So it is a feature of monads. If you implement a monad in another language, you're still going to be defining fmap (or an equivalent), which lets you use this.


> I might describe it as “pathologically easy” to compose functions in Haskell

Maybe because "composing functions" is the whole point of category theory, monads and Haskell?


The point of category theory is composing morphisms! Functions are morphisms in the Set category. Haskell has something which looks very similar to category theory, but the functions and types in Haskell do not form a category. I would call it “category theory inspired”.


Thank you for the clarification.

But still, since it's all about composition, the simplicity is a direct consequence IMHO.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: