我有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
的{{1}}值是多少?
我试过例如:
(->)
*Exercises Data.Monoid> mempty :: (-> Integer Bool)
<interactive>:21:15: error: parse error on input `Integer'
中mempty
的实施情况如何?
我看了hackage来源:
monoid
并且无法找到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}
的{{1}}是Product Integer
。
答案 0 :(得分:5)
$scope.model = $scope.options[2]
不是类型常量(没有类型(->)
的任何值),因此不能有monoid实例。(->)
有一个monoid实例,则类型常量b
(或a -> b
)确实有一个monoid实例,而(->) a b
会生成一个函数,忽略它输入并返回mempty
mempty
作为值。如果你看一下
b
行instance Monoid b => Monoid (a -> b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x
实现了这一点。
mempty _ = mempty
的{{1}}类型是什么?它是mempty
,因为a -> b
需要是a -> b
类型的值。所以
mempty
告诉我们,a -> b
mempty _ = mempty
是一个函数,它会丢弃其输入并返回 mempty
,类型为{{ 1}} 即可。此定义中出现两次名称a -> b
,指的是不同的函数/值。
让我们来看一些具体的例子:
你试过
mempty
这在语法上是错误的。你想尝试
b
产生新错误
mempty
因为mempty :: (-> Integer Bool)
没有monoid实例。
你试过
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
类型。
现在尝试
Product Integer
在此示例中,b
引用类型a -> b
的某个值,因此是一个函数。因此,> let f = mempty :: a -> Product Integer
> f 'x'
Product {getProduct = 1}
中的类型变量mempty
在这种情况下引用类型a -> Product Integer
。