top | item 38811498

(no title)

spicebox | 2 years 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.

discuss

order

ChadNauseam|2 years ago

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)

nyssos|2 years ago

> 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.