为什么WrappedMonad和WrappedArrow?

时间:2015-02-12 01:52:54

标签: haskell applicative

为什么WrappedMonadWrappedArrow类型存在?是因为Monad s不是Applicative吗?鉴于WrappedArrow存在,应该是实例

Arrow a => Applicative (Arrow a b) 

简单地构建到Haskell本身,就像Applicative现在是Monad的超类一样?

2 个答案:

答案 0 :(得分:9)

WrappedMonad几乎是这样。我想它正在变得(也许已经是)基本上已经过时了。但WrappedArrow更难,因为Arrow类型和Applicative类型有不同类型,* -> * -> ** -> *。并且由于GHC实例解析的工作方式,添加实例(我假设额外的Arrow是一个错字)

instance Arrow a => Applicative (a b)

意味着具有两个或更多参数的 no 类型构造函数可以提供Applicative而不会给出Arrow - 这似乎相当激烈。

Applicative (a b) =>添加超类Arrow a的相反选项看起来更合适 - 除了你不能拥有像b这样的类型的超类。这样的超类对其他事情也很有用,并且已经多次提出过,所以我认为很难很好地实现。

答案 1 :(得分:1)

我觉得the DerivingVia extension为这种新型包装纸赋予了新的生命。假设由于某种原因,我们想为一个类型编写MonadMonadPlus实例,然后为ApplicativeAlternative搭载它们:

newtype StT s m a = StT { runStT :: s -> m (a, s) }
    deriving Functor

instance Monad m => Monad (StT s m) where
    return a = StT $ \s -> return (a, s)
    m >>= f = StT $ \s -> m `runStT` s >>= \(a, t) -> f a `runStT` t

instance MonadPlus m => MonadPlus (StT s m) where
    mzero = StT $ \_ -> mzero
    m `mplus` n = StT $ \s -> (m `runStT` s) `mplus` (n `runStT` s)

通常,我们必须编写样板实例:

instance Monad m => Applicative (StT s m) where
    pure = return
    (<*>) = ap

instance MonadPlus m => Alternative (StT s m) where
    empty = mzero
    (<|>) = mplus

使用DerivingViaWrappedMonad可以用我认为更好的方式将其拼写出来。

newtype StT s m a = StT { runStT :: s -> m (a, s) }
    deriving Functor
    deriving (Applicative, Alternative) via WrappedMonad (StT s m)

请注意,预先存在的派生子句不受影响。另一个不错的感觉是,可以推断出必要的超类约束。