如果 a 有 Monoid,是否可以为 Identity a 编写一个 Alternative 实例?

我想AlternativeIdentitynewtype编写一个实例。骨架并不难:

instance Alternative Identity where
  empty = _
  (<|>) = _

但是,对于所有类型的实现都是不可能的。如果我有一个 Monoid 实例,那会很容易a

instance Alternative Identity where
  empty = Identity mempty
  (Identity a) <|> (Identity a') = Identity (a <> a')

有没有办法告诉编译器我只想Alternative在内部类型有 Monoid 实例时定义实例?由于a没有在任何地方提及,我不能只使用约束Monoid a =>

回答

一个Alternative必须提供empty所有类型a,没有任何限制。否则,它不履行Alternative合同。

也就是说,如果我们有一个实例Alternative f,我们必须有

empty :: forall a . f a

没有任何进一步的限制。

因此,Identity不是Alternative

这是一个已知问题,在许多类似的类型类中都有发现。例如,许多人会喜欢一个Functor Set实例,但这需要

fmap :: (a -> b) -> Set a -> Set b

对于所有类型aand b,而上述功能只能在Ord类型上实现。因为我们不能添加约束,所以我们没有得到函子。

不过,可以尝试使用更通用的类型类来考虑额外的约束。也许像

class CFunctor c f where
fmap :: (c a, c b) => (a->b) -> f a -> f b
class CFunctor c f => CApplicative c f where
empty :: c a => f a
(<*>) :: (c a, c b, c (a->b)) => f (a->b) -> f a -> f b

但这些不是图书馆中的“标准”。(我猜在 hackage 上应该有类似于上面受约束的类变体的东西。)


以上是如果 a 有 Monoid,是否可以为 Identity a 编写一个 Alternative 实例?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>