sim*_*uff 1 haskell applicative monoids
我正在学习 Haskell 并尝试从《Haskell 编程从第一原理》一书中进行练习,并且我正在尝试编写 Pair 类型的应用程序
data Pair a = Pair a a deriving Show
Run Code Online (Sandbox Code Playgroud)
我在网上看到了一些其他示例,但我正在尝试一些不同的应用函子,我正在尝试利用这种类型的幺半群结构。这是我所拥有的
data Pair a = Pair a a deriving (Show, Eq)
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
instance Semigroup a => Semigroup (Pair a) where
(Pair x y) <> (Pair x' y') = Pair (x <> x') (y <> y')
instance Applicative Pair where
pure x = Pair x x
(Pair f g) <*> p = fmap f p <> fmap g p
Run Code Online (Sandbox Code Playgroud)
不幸的是这不会编译:
* No instance for (Semigroup b) arising from a use of `<>'
Possible fix:
add (Semigroup b) to the context of
the type signature for:
(<*>) :: forall a b. Pair (a -> b) -> Pair a -> Pair b
* In the expression: fmap f p <> fmap g p
In an equation for `<*>': (Pair f g) <*> p = fmap f p <> fmap g p
In the instance declaration for `Applicative Pair'
Run Code Online (Sandbox Code Playgroud)
这就是我的堆栈;我不明白如何将类型类约束添加到 Applicative 定义中,我认为创建 Semigroup 的类型 Pair 实例就足够了。
我见过的其他解决方案就像
Pair (f g) <*> Pair x y = Pair (f x) (g y)
Run Code Online (Sandbox Code Playgroud)
但这些解决方案不利用 Pair 类型的幺半群部分
是否有可能以我没有尝试的方式使其适用?
虽然这确实Applicative是代表幺半群函子的类(特别是,Hask内函子是幺半群的),但不幸的是,Allen 和 Moronuki 以一种似乎表明 和Monoid类之间存在直接关系的方式呈现了这一点Applicative。一般来说,不存在这种关系!(该Writer类型确实Applicative根据Monoid类定义了一个特定实例,但这是一种极其特殊的情况。)
\n这在另一个 SO 问题上引发了相当广泛的讨论。
\xe2\x80\x9cmonoidal\xe2\x80\x9d in \xe2\x80\x9cmonoidal functor\xe2\x80\x9d 指的是类别对象上的幺半结构,即 Haskell 类型上的。也就是说,您可以将任意两种类型组合为元组类型。这本身与类没有任何关系Monoid,类是关于组合两个值的组合为相同类型的值。
Pair确实允许Applicative实例,但您不能将其基于Semigroup实例,尽管定义实际上看起来非常相似:
instance Applicative Pair where\n pure x = Pair x x\n Pair f g <*> Pair p q = Pair (f p) (g q)\nRun Code Online (Sandbox Code Playgroud)\n\n但是,您现在可以根据此Semigroup定义实例:
instance Semigroup a => Semigroup (Pair a) where\n (<>) = liftA2 (<>)\nRun Code Online (Sandbox Code Playgroud)\n\n这确实是任何Semigroup一个有效的例子,但它通常不是您想要的定义(通常,容器有一个自然的组合操作,永远不会触及所包含的元素,例如列表串联)。