在幺半群和半群中使用了Alternative Alt的示例。
为什么没有它我们就不能写示例呢?
{-# LANGUAGE FlexibleInstances #-}
instance Alternative f => Semigroup (f a) where
(<>) = <|>
instance Alternative f => Monoid (f a) where
mempty = empty
如果我们能写出它,那么我们能在函数中用(幺半群(f a),应用型f)代替Alternative吗?
3条答案
按热度按时间ulydmbyx1#
您可以使用它为任何
Alternative
派生Monoid
Alt
是一个新类型,因为有很多方法可以描述f a
的应用类型Monoid
的行为。例如Applicative
提升:Ap
.您给予的示例最大程度地重叠,任何应用类型的
Monoid
示例现在都被强制为Alternative
示例,完全忽略a
参数。在许多情况下,这是不正确的,例如
Semigroup a => Semigroup (Maybe a)
与从Alternative Maybe
得到的Semigroup
不同。可以使用一个相当新的特性
QuantifiedConstraints
来量化类型构造函数forall x. Monoid (f x)
的参数。gdx19jrr2#
您使用了**
(<|>) :: Alternative f => f a -> f a -> f a
和empty :: Alternative f => f a
。正如签名所示,这些函数是为Applicative f => f a
类型的项定义的。因此,您只能使用这些函数来处理此类项,因此,如果您使用f a
,例如,使用mempty = empty
定义mempty :: f a
,则要求f
是Alternative
**类型类的成员。也就是说,虽然很多数据类型 * 可以 * 有一个
Semigroup
和Monoid
示例,定义为如何实现Alternative
,但这本身不是最好的示例。是的,Alternative
是应用函子上的 * 幺半群 *,但这本身不应该是这些数据类型上的 * 幺半群示例。yv5phkfx3#
如果您建议的示例以这种形式存在,* 每个 * 匹配
f a
的类型都会立即服从它。不幸的是,
ResultsSum a
与f a
匹配,但它不是Alternative
;它甚至不是一个函子,也不可能是(更确切地说,它是Contravariant
)。然而,编译器在解析示例时并不考虑这一点:它只看到两个示例声明,它们的头部都声称使ResultsSum
成为半群,这触发了歧义示例错误。当然,这个例子 * 可以 * 用
{-# OVERLAPPING #-}
pragma来处理,但是最好避免示例重叠,因为它们会导致奇怪的结果。这是不必要的,因为你也可以派生那些via
和Alternative
的示例。尽管我个人更愿意用相反的方法:首先定义Monoid
示例,然后根据它定义Alternative
。