haskell / mtl

The Monad Transformer Library
http://www.haskell.org/haskellwiki/Monad_Transformers
Other
362 stars 63 forks source link

ContT is strange? #91

Closed sdzx-1 closed 2 years ago

sdzx-1 commented 2 years ago

hello, everyone. I found ContT a bit weird.

newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }

Why can't we define it like this?


newtype ContT r m a = ContT {runContT :: (m a -> m r) -> m r}

evalContT :: (Monad m) => (m a -> m r) -> ContT r m a -> m r
evalContT f m = runContT m f

instance Functor m => Functor (ContT r m) where
  fmap f m = ContT $ \c -> runContT m (c . fmap f)

instance Applicative m => Applicative (ContT r m) where
  pure x = ContT ($ pure x)
  f <*> v = ContT $ \c -> runContT f $ \g -> runContT v (\tmp -> c (g <*> tmp))

-- never del this
-- res <- runContT <$> (k <$> x)
-- res c
instance (Monad m) => Monad (ContT r m) where
  m >>= k = ContT $ \c -> runContT m ((<$>) k >=> (($ c) . runContT))

instance MonadTrans (ContT r) where
  lift m = ContT $ \g -> g m

instance MonadIO m => MonadIO (ContT r m) where
  liftIO io = ContT $ \c -> c (liftIO io)

https://github.com/EMQ-YangM/fused-effects-cont/blob/5fd9dc23b3640a9702acacdf55f450dfb6c719db/src/Cont.hs#L24-L52 It seems more normal to look at it this way.

I hope I can use ContT in fused-effects. If I have any mistakes, please let me know.

Lysxia commented 2 years ago

Aren't these just different types with different purposes? There is no absolute "right" or "wrong", which is better depends on the job. However, a big part of the appeal of ContT is that you can define its Functor/Applicative/Monad instances uniformly for all m, not only monads, so this version wouldn't be an acceptable replacement for those who rely on that feature.