我可以自动实现类吗?
Can I automatically implement classes?
在 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
的实例。
是否可以避免这种重复性工作?
当有两个地方可以派生 Applicative
实例时,问题就来了。例如,假设 m
是类型 a b
,其中 Arrow a
。然后从这个定义中也有一个明显的 Applicative
实例。编译器应该使用哪一个?当然,结果应该是一样的,但是 Haskell 无法检查这一点。通过让我们写出实例,Haskell 至少迫使我们考虑定义的一致性。
如果需要,Control.Applicative
中有 WrappedMonad
class,它为所有明显的实例提供了 newtype
包装器,但使用 WrapMonad
而且 unwrapMonad
一直都没有那么有吸引力。
目前不可能,但如果您更改现有库以支持它,则可以。打开 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
或方法定义)将继承这些默认实现。我不确定为什么没有这样做。
在 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
的实例。
是否可以避免这种重复性工作?
当有两个地方可以派生 Applicative
实例时,问题就来了。例如,假设 m
是类型 a b
,其中 Arrow a
。然后从这个定义中也有一个明显的 Applicative
实例。编译器应该使用哪一个?当然,结果应该是一样的,但是 Haskell 无法检查这一点。通过让我们写出实例,Haskell 至少迫使我们考虑定义的一致性。
如果需要,Control.Applicative
中有 WrappedMonad
class,它为所有明显的实例提供了 newtype
包装器,但使用 WrapMonad
而且 unwrapMonad
一直都没有那么有吸引力。
目前不可能,但如果您更改现有库以支持它,则可以。打开 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
或方法定义)将继承这些默认实现。我不确定为什么没有这样做。