为什么WrappedMonad
和WrappedArrow
类型存在?是因为Monad
s不是Applicative
吗?鉴于WrappedArrow
存在,应该是实例
Arrow a => Applicative (Arrow a b)
简单地构建到Haskell本身,就像Applicative
现在是Monad
的超类一样?
答案 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为这种新型包装纸赋予了新的生命。假设由于某种原因,我们想为一个类型编写Monad
和MonadPlus
实例,然后为Applicative
和Alternative
搭载它们:
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
使用DerivingVia
,WrappedMonad
可以用我认为更好的方式将其拼写出来。
newtype StT s m a = StT { runStT :: s -> m (a, s) }
deriving Functor
deriving (Applicative, Alternative) via WrappedMonad (StT s m)
请注意,预先存在的派生子句不受影响。另一个不错的感觉是,可以推断出必要的超类约束。