Hacker News new | ask | show | jobs
by spicebox 906 days ago
Monads don’t compose, effects do. ‘IO a’ works great until until you need to add another effect, for example ‘Maybe’. Then you need to bring in monad transformers and create your own monad combining the two, then rewrite all your code to lift the effects from one monad to the other. And you have to do this every time you want to add a new effect.
1 comments

Not to mention you need monadic and nonmonadic versions of every higher order function (or so it feels like) - map / mapM, fold / foldM, etc.

This is even worse in Rust, which requires you to have a separate implementation for every effect as well (since it doesn't have higher kinded types)

> Not to mention you need monadic and nonmonadic versions of every higher order function (or so it feels like) - map / mapM

This is more a weakness of Haskell's standard library (which is despite its reputation not very friendly to category theory) than an inherent problem with monads. A more general `map` would look something like this

    class Category c => FunctorOf c f where
    map :: c a b -> c (f a) (f b)

    fmap :: FunctorOf (->) f => (a -> b) -> f a -> f b
    fmap = map

    type Kleisli m a b = a -> m b
    mapM :: (Monad m, FunctorOf (Kleisli m) f) => (a -> m b) -> f a -> m (f b)
    mapM = map

    type Op c a b = c b a
    contramap :: FunctorOf (Op (->)) f => (a -> b) -> f b -> f a
    contramap = map

    type Product c d (a,x) (b,y) = (c a b, d x y)
    bimap :: FunctorOf (Product (->) (->)) f => (a -> b, x -> y) -> f (a, x) -> f (b, y)
    bimap = map

    -- and so on 
but this would require somewhat better type-level programming support for the ergonomics to work out.