我具有以下带有Monoid和Semigroup实例的数据类型:

newtype Combine a b =
  Combine { unCombine :: a -> b }

instance (Semigroup b)
  => Semigroup (Combine a b) where
  Combine {unCombine=f} <> Combine {unCombine=g} = Combine (f <> g)

instance (Semigroup b, Monoid b)
  => Monoid (Combine a b) where
  mempty = Combine mempty
  mappend = (<>)


我要配置它,函数mempty(->)值是多少?

我尝试过例如:

*Exercises Data.Monoid> mempty :: (-> Integer Bool)
<interactive>:21:15: error: parse error on input `Integer'


memptymonoid的实现是什么样的?

我查看了黑客源:

instance Monoid b => Monoid (a -> b) where
        mempty _ = mempty
        mappend f g x = f x `mappend` g x


并且找不到mempty的实现。

也许要弄清楚我的意思,请考虑以下示例:

*Exercises Data.Monoid> mempty :: (Product Integer)
Product {getProduct = 1}


Product Integer的空位是Product {getProduct = 1}

最佳答案

类型构造函数(->)不是类型常量(没有任何类型的(->)值),因此不能有一个monoid实例。
如果类型b具有一个monoid实例,则类型常量a -> b(或(->) a b)确实具有一个monoid实例,并且mempty产生一个函数,该函数将忽略其输入并返回memptyb值。


如果你看

instance Monoid b => Monoid (a -> b) where
    mempty _ = mempty
    mappend f g x = f x `mappend` g x


mempty _ = mempty行实现了这一点。

memptya -> b是什么类型?它是a -> b,因为mempty必须是a -> b类型的值。所以

mempty _ = mempty

告诉我们,memptya -> b是一个函数,它将丢弃其输入并返回mempty,即类型为b的值。在此定义中两次出现的名称mempty表示不同的功能/值。

让我们举一些具体的例子:


你试过了

mempty :: (-> Integer Bool)


这在语法上是错误的。你想尝试

mempty :: (->) Integer Bool


产生一个新的错误

<interactive>:5:1: error:
   • No instance for (Monoid Bool) arising from a use of ‘mempty’
   • In the expression: mempty :: (->) Integer Bool
     In an equation for ‘it’: it = mempty :: (->) Integer Bool


因为Bool没有一个monoid实例。
你试过了

mempty :: (Product Integer)


它起作用并产生Product {getProduct = 1}作为值。
这就告诉您Product Integer有一个monoid实例。因此,我们可以尝试将Product Integer设置为b中的a -> b类型。
现在尝试

> let f = mempty :: a -> Product Integer
> f 'x'
Product {getProduct = 1}


在此示例中,mempty引用类型为a -> Product Integer的某个值,因此是一个函数。因此,在这种情况下,来自t的类型变量mempty :: (Monoid t) => t引用类型a -> Product Integer

关于haskell - 数据类型的含义是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44818972/

10-11 19:59