首页 文章

我可以自动实现课程吗?

提问于
浏览
9

在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 回答

  • 3

    目前还不可能,但如果您更改现有库以支持此功能 . 打开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 或方法定义)将继承这些默认实现 . 我完成了'm not sure why this wasn' .

  • 2

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

    如果你愿意, Control.Applicative 中有 WrappedMonad 类,它提供了 newtype 包装器的所有明显实例,但是始终使用 WrapMonadunwrapMonad 并不具有吸引力 .

相关问题