如果 a 有一个 Monoid,是否可以为 Identity a 编写一个 Alternative 实例?
Is it possible to write an Alternative instance for Identity a if there's a Monoid for a?
我想为 Identity
新类型编写一个 Alternative
实例。骨架不硬:
instance Alternative Identity where
empty = _
(<|>) = _
但是,不可能对所有类型都实施。如果我有一个 a
的 Monoid 实例,那会很容易:
instance Alternative Identity where
empty = Identity mempty
(Identity a) <|> (Identity a') = Identity (a <> a')
有没有办法告诉编译器我只想定义 Alternative
实例,当里面的类型有一个 Monoid 实例?由于 a
没有在任何地方提到,我不能只使用约束 Monoid a =>
.
Alternative
必须为 所有 类型 a
提供 empty
,没有任何限制。否则,它不履行Alternative
合同。
也就是说,如果我们有一个实例Alternative f
,我们必须有
empty :: forall a . f a
没有任何进一步的限制。
因此,Identity
不是 Alternative
。
这是一个已知问题,在许多类似类型 classes 中发现。例如,许多人会喜欢 Functor Set
实例,但这需要
fmap :: (a -> b) -> Set a -> Set b
适用于所有类型a
和b
,而上述功能只能在Ord
类型上实现。由于我们无法添加约束,因此我们没有得到函子。
仍然可以尝试使用一种更通用的类型 class 来考虑额外的限制。也许像
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 上应该有类似于上面受约束的 class 变体的东西。)
我想为 Identity
新类型编写一个 Alternative
实例。骨架不硬:
instance Alternative Identity where
empty = _
(<|>) = _
但是,不可能对所有类型都实施。如果我有一个 a
的 Monoid 实例,那会很容易:
instance Alternative Identity where
empty = Identity mempty
(Identity a) <|> (Identity a') = Identity (a <> a')
有没有办法告诉编译器我只想定义 Alternative
实例,当里面的类型有一个 Monoid 实例?由于 a
没有在任何地方提到,我不能只使用约束 Monoid a =>
.
Alternative
必须为 所有 类型 a
提供 empty
,没有任何限制。否则,它不履行Alternative
合同。
也就是说,如果我们有一个实例Alternative f
,我们必须有
empty :: forall a . f a
没有任何进一步的限制。
因此,Identity
不是 Alternative
。
这是一个已知问题,在许多类似类型 classes 中发现。例如,许多人会喜欢 Functor Set
实例,但这需要
fmap :: (a -> b) -> Set a -> Set b
适用于所有类型a
和b
,而上述功能只能在Ord
类型上实现。由于我们无法添加约束,因此我们没有得到函子。
仍然可以尝试使用一种更通用的类型 class 来考虑额外的限制。也许像
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 上应该有类似于上面受约束的 class 变体的东西。)