haskell 在Monoid示例中需要什么Alt?

xcitsw88  于 2022-11-24  发布在  其他
关注(0)|答案(3)|浏览(122)

在幺半群和半群中使用了Alternative Alt的示例。
为什么没有它我们就不能写示例呢?

{-# LANGUAGE FlexibleInstances #-}
instance Alternative f => Semigroup (f a) where
  (<>) = <|>

instance Alternative f => Monoid (f a) where
  mempty = empty

如果我们能写出它,那么我们能在函数中用(幺半群(f a),应用型f)代替Alternative吗?

ulydmbyx

ulydmbyx1#

您可以使用它为任何Alternative派生Monoid

{-# Language DerivingVia #-}

data F a = ..
  deriving (Semigroup, Monoid)
  via Alt F a

instance Functor     F where ..
instance Applicative F where ..
instance Alternative F where ..

Alt是一个新类型,因为有很多方法可以描述f a的应用类型Monoid的行为。例如Applicative提升:Ap.

{-# Language DerivingVia #-}

data G a = ..
  deriving (Semigroup, Monoid, Num, Bounded)
  via Ap G a

instance Functor     G where ..
instance Applicative G where ..

您给予的示例最大程度地重叠,任何应用类型的Monoid示例现在都被强制为Alternative示例,完全忽略a参数。
在许多情况下,这是不正确的,例如Semigroup a => Semigroup (Maybe a)与从Alternative Maybe得到的Semigroup不同。
可以使用一个相当新的特性QuantifiedConstraints来量化类型构造函数forall x. Monoid (f x)的参数。

{-# Language QuantifiedConstraints #-}
..

type Alternative' :: (Type -> Type) -> Constraint

class    (forall x. Monoid (f x)) => Alternative' f
instance (forall x. Monoid (f x)) => Alternative' f
gdx19jrr

gdx19jrr2#

您使用了**(<|>) :: Alternative f => f a -> f a -> f aempty :: Alternative f => f a。正如签名所示,这些函数是为Applicative f => f a类型的项定义的。因此,您只能使用这些函数来处理此类项,因此,如果您使用f a,例如,使用mempty = empty定义mempty :: f a,则要求fAlternative**类型类的成员。
也就是说,虽然很多数据类型 * 可以 * 有一个SemigroupMonoid示例,定义为如何实现Alternative,但这本身不是最好的示例。是的,Alternative是应用函子上的 * 幺半群 *,但这本身不应该是这些数据类型上的 * 幺半群示例。

yv5phkfx

yv5phkfx3#

如果您建议的示例以这种形式存在,* 每个 * 匹配f a的类型都会立即服从它。

newtype ResultsSum a = ResultsSum {funToSum :: a -> Int}

instance Semigroup (ResultsSum a) where
  ResultsSum p <> ResultsSum q = ResultsSum $ \x -> p x + q x

不幸的是,ResultsSum af a匹配,但它不是Alternative;它甚至不是一个函子,也不可能是(更确切地说,它是Contravariant)。然而,编译器在解析示例时并不考虑这一点:它只看到两个示例声明,它们的头部都声称使ResultsSum成为半群,这触发了歧义示例错误。
当然,这个例子 * 可以 * 用{-# OVERLAPPING #-} pragma来处理,但是最好避免示例重叠,因为它们会导致奇怪的结果。这是不必要的,因为你也可以派生那些viaAlternative的示例。尽管我个人更愿意用相反的方法:首先定义Monoid示例,然后根据它定义Alternative

相关问题