Haskell 尝试使用幺半函子的应用程序实例

Haskell 尝试使用幺半函子的应用程序实例,haskell,applicative,monoids,Haskell,Applicative,Monoids,我正在学习Haskell,并尝试从《Haskell从第一原理编程》一书中做练习,我正在尝试为Pair类型编写应用程序 data Pair a = Pair a a deriving Show 我在网上看到了一些其他的例子,但我尝试了一些不同的应用程序函子,我试图利用这种类型的幺半体结构。这是我的 data Pair a = Pair a a deriving (Show, Eq) instance Functor Pair where fmap f (Pair x y) = Pa

我正在学习Haskell,并尝试从《Haskell从第一原理编程》一书中做练习,我正在尝试为Pair类型编写应用程序

 data Pair a = Pair a a deriving Show
我在网上看到了一些其他的例子,但我尝试了一些不同的应用程序函子,我试图利用这种类型的幺半体结构。这是我的

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
数据对a=对a派生(显示,等式)
实例函子对,其中
fmap f(对x y)=对(对x)(对y)
实例半群a=>半群(对a),其中
(对xy)(对x'y')=对(x x')(y'))
实例应用程序对,其中
纯x=对x
(配对f g)p=fmap f p fmap g p
不幸的是,这不会编译:

* 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'
*没有因使用`'而产生的(半群b)实例
可能的解决方案:
将(半群b)添加到
以下项的类型签名:
()::全部a b。线对(a->b)->线对a->线对b
*在表达式中:fmap f p fmap g p
在`'的方程式中:(对f g)p=fmap f p fmap g p
在“应用程序对”的实例声明中
这就是我的位置;我不知道如何将typeclass约束添加到应用程序定义中,我认为创建半群的类型对实例就足够了

我看到的其他解决方案如下

Pair (f g) <*> Pair x y = Pair (f x) (g y)
Pair(fg)Pair x y=Pair(fx)(gy)
但这些解决方案并没有利用对类型的单倍体部分

 data Pair a = Pair a a deriving Show

甚至有可能以我不尝试的方式使此应用程序化吗?

我不认为
Pair
是一种
applicative
您想要的方式,
applicative
指出

(<*>) :: f (a -> b) -> f a -> f b
()::f(a->b)->f a->f b
应该适用于第一个位置的所有函数,而您需要

(<*>) :: Semigroup b => f (a -> b) -> f a -> f b.
()::半群b=>f(a->b)->fa->fb。

如果Pair总是一个
半群
(比如
可能
或者
列表
),那么你的推理是合理的,但是你需要
Pair
-containee的先决条件是
半群

我不认为
Pair
是一个
应用的
,就像你希望的那样,
Applicative
声明

(<*>) :: f (a -> b) -> f a -> f b
()::f(a->b)->f a->f b
应该适用于第一个位置的所有函数,而您需要

(<*>) :: Semigroup b => f (a -> b) -> f a -> f b.
()::半群b=>f(a->b)->fa->fb。

如果Pair始终是
半群
(例如
可能
列表
),您的推理将是合理的,但是您需要
Pair
-containee的先决条件是
半群

,尽管
Applicative
确实是表示幺半群函子的类(特别是,Hask内函子是幺半群),Allen和Moronuki以一种似乎暗示了
幺半群
应用类
之间的直接关系的方式不幸地提出了这一点。一般来说,没有这种关系!(
Writer
类型确实基于
Monoid
类定义了一个特定的
Applicative
实例,但这是一个非常特殊的情况。)
这就产生了

什么是“幺半函子”中的“幺半”引用是类别对象上的一个幺半体结构,即Haskell类型。也就是说,您可以将任意两种类型组合为一个元组类型。这本身与
Monoid
类无关,该类将单个类型的两个值组合为同一类型的值

Pair
确实允许使用
Applicative
实例,但不能基于
半组
实例,尽管定义实际上非常相似:

instance Applicative Pair where
  pure x = Pair x x
  Pair f g <*> Pair p q = Pair (f p) (g q)

对于任何应用程序来说,这的确是一个有效的
半组
实例,但它通常不是您想要的定义(通常,容器有一个自然的组合操作,它从不涉及所包含的元素,例如列表串联)Allen&Moronuki以一种似乎暗示
幺半群
应用类
之间存在直接关系的方式不幸地提出了这一点。通常,没有这种关系!(
Writer
类型确实基于
Monoid
类定义了一个特定的
Applicative
实例,但这是一个非常特殊的情况。)
这就产生了

什么是“幺半函子”中的“幺半”引用是类别对象上的一个幺半体结构,即Haskell类型。也就是说,您可以将任意两种类型组合为一个元组类型。这本身与
Monoid
类无关,该类将单个类型的两个值组合为同一类型的值

Pair
确实允许使用
Applicative
实例,但不能基于
半组
实例,尽管定义实际上非常相似:

instance Applicative Pair where
  pure x = Pair x x
  Pair f g <*> Pair p q = Pair (f p) (g q)

对于任何应用程序来说,这的确是一个有效的
半组
实例,但它通常不是您想要的定义(通常,容器有一个自然的组合操作,它从不涉及所包含的元素,例如列表串联)“<代码> >配对<代码>不能按照您想要的方式生成<代码>应用程序/代码>,因为<代码>应用f>代码>要求<代码> f a < /代码>“感觉应用y”,对于任何<代码> a <代码>,甚至非代码>半群 <代码> a < /代码> s。考虑编写另一个类并实现它:

class CApplicative f where
    type C f
    pure :: C f a => a -> f a
    app  :: C f b => f (a -> b) -> f a -> f b

instance CApplicative Pair where
    type C Pair = Semigroup
    pure x = Pair x x
    app (Pure f g) p = fmap f p <> fmap g p
class cappplicative f其中
C型和f型
纯::C f a=>a->f a
应用程序::cf b=>f(a->b)->f a->f b
实例capapplicative对在哪里
C型对=半群
纯x=对x
app(纯f g)p=fmap f p fmap g p

正确:
不能成为