我可以自动实现课程吗?

时间:2015-04-02 13:36:16

标签: haskell scalaz

在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中,我必须一次又一次地为每个Applicative提供Monad的实例。

是否可以避免这种重复性的工作?

2 个答案:

答案 0 :(得分:3)

当有两个地方可以从中派生Applicative实例时,会出现问题。例如,假设ma b所在的Arrow a类型。然后,这个定义中也有一个明显的Applicative实例。编译器应该使用哪一个?当然,它应该是相同的,但Haskell没有办法检查这一点。通过让我们写出实例,Haskell至少迫使我们考虑定义的一致性。

如果您愿意,WrappedMonad中有Control.Applicative个类,它使用newtype包装器提供所有明显的实例,但使用WrapMonadunwrapMonad所有的时间都不那么吸引人。

答案 1 :(得分:2)

目前还不可能,但如果您更改了现有的库以支持此功能。打开DefaultSignatures会让你写

class Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b

    default pure :: Monad f => a -> f a
    default (<*>) :: Monad f => f (a -> b) -> f a -> f b
    pure = return
    (<*>) = ap

然后,一旦您实现了instance Monad M where {- ... -},一个简单的instance Applicative M(没有where或方法定义)将继承这些默认实现。我不知道为什么没有这样做。