我有以下数据类型:
data HVF a b = HVF { h1 :: !a
, l1 :: !Int
} deriving (Show, Eq)
instance Monoid (HVF a b) where {...}
我尝试写一个函数:
hvf :: (Num a, Ord a) => Fold a (HVF a b)
hvf = Fold tally summarize
where
tally x = HVF x
summarize (HVF x y) = (HVF x y)
与
data Fold i o = forall m . Monoid m => Fold (i -> m) (m -> o)
但是我收到了错误:
• Couldn't match type ‘Int -> HVF a b0’ with ‘HVF a b1’
Expected type: (Int -> HVF a b0) -> HVF a b
Actual type: HVF a b1 -> HVF a b
• In the second argument of ‘Fold’, namely ‘summarize’
In the expression: Fold tally summarize
In an equation for ‘hvf’:
hvf
= Fold tally summarize
where
tally x = HVF x
summarize (HVF x y) = (HVF x y)
• Relevant bindings include
hvf :: Fold a (HVF a b) (bound at src/Data/HVFScanner/HVF.hs:119:1)
|
119 | hvf = Fold tally summarize
|
我不明白,任何人都可以用英语解释吗?
其他信息......
Fold
来自https://github.com/Gabriel439/slides/blob/master/munihac/foldmap.md#-in-one-slide
答案 0 :(得分:3)
Fold
有两个值,一个tally
函数将输入值注入某个monoid,一个summarize
函数从monoid中提取结果。
非正式:
tally :: i -> m
summarize :: m -> o
其中m
是Monoid
。
在您的代码中
hvf :: (Num a, Ord a) => Fold a (HVF a b)
hvf = Fold tally summarize
where
tally x = HVF x
summarize (HVF x y) = (HVF x y)
您的tally
类型为a -> Int -> HVF a b
,其中(因为类型中的->
是右关联的)相当于a -> (Int -> HVF a b)
。因此,类型检查器假定您的输入类型i
为a
,而您的幺半群类型m
为Int -> HVF a b
。
您的summarize
类型为HVF a b1 -> HVF a b2
。但是,要与Fold tally
一起使用,它需要m -> o
类型m
为Int -> HVF a b
。这是错误消息抱怨的内容:summarize
的参数类型为HVF a b1
,但summarize
用于需要接受Int -> HVF a b
的上下文中
我不理解你的其余代码,但我认为你在HVF
忘记了对tally
的争论。也许像tally x = HVF x 0
?
答案 1 :(得分:3)
错误实际上在于tally
。那应该是类型a -> m
,其中幺半群在这种情况下是HVF a b
,即
tally :: a -> HVF a b
但你已经实施了什么
tally x = HVF x
实际上有a -> Int -> HVF a b
类型,因为HVF x
仍然缺少Int
字段,即您只有部分应用HVF
值构造函数,由于Haskell在 curried模式中的工作方式,缺少参数会自动延迟为tally
函数的额外参数。
有点奇怪的是,这本身就是而不是类型错误:签名a -> Int -> HVF a b
实际上也形式为a -> m
,但是在这种情况下,m
是函数类型Int -> HVF a b
。实际上,该函数类型也有一个Monoid
实例!
但这意味着您还需要类型
summarise :: (Int -> HVF a b) -> HVF a b
...但这不是summarise
的类型,只是
summarise :: HVF a b -> HVF a b
因此误导性错误信息。