在Scalaz中,每个 Monad
实例都自动成为 Applicative
的实例 .
implicit val listInstance = new Monad[List] {
def point[A](a: => A) = List(a)
def bind[A, B](fa: List[A])(f: A => List[B]) = fa flatMap f
}
List(2) <*> List((x: Int) => x + 1) // Works!
另一个例子: Arrow
自动为 Profunctor
.
但是,在Haskell中,我必须一次又一次地为 Monad
提供 Applicative
的实例 .
有可能避免这种重复的工作吗?
2 回答
目前还不可能,但如果您更改现有库以支持此功能 . 打开DefaultSignatures会让你写
然后,一旦实现
instance Monad M where {- ... -}
,一个简单的instance Applicative M
(没有where
或方法定义)将继承这些默认实现 . 我完成了'm not sure why this wasn' .当有两个地方可以从中派生
Applicative
实例时,就会出现问题 . 例如,假设m
是a b
,其中Arrow a
. 然后,这个定义中也有一个明显的Applicative
实例 . 编译器应该使用哪一个?当然,它应该是相同的,但Haskell没有办法检查这一点 . 通过让我们写出实例,Haskell至少迫使我们思考定义的一致性 .如果你愿意,
Control.Applicative
中有WrappedMonad
类,它提供了newtype
包装器的所有明显实例,但是始终使用WrapMonad
和unwrapMonad
并不具有吸引力 .