我有关于Couldn't match type ‘a’ with ‘a1’
错误失败的Haskell代码:
bar :: [Int] -> (a -> Int -> a) -> a -> a
bar ns fp ap = snd $ foldl fn (fp, ap) ns
where fn :: ((a -> Int -> a), a) -> Int -> ((a -> Int -> a), a)
fn (f, x) i = (fp, (f x (i + length(ns))))
以下是详细的错误消息:
t.hs:4:24: error:
• Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for:
bar :: forall a. [Int] -> (a -> Int -> a) -> a -> a
at t.hs:1:8
‘a1’ is a rigid type variable bound by
the type signature for:
fn :: forall a1.
(a1 -> Int -> a1, a1) -> Int -> (a1 -> Int -> a1, a1)
at t.hs:3:15
Expected type: a1 -> Int -> a1
Actual type: a -> Int -> a
• In the expression: fp
In the expression: (fp, (f x (i + length (ns))))
In an equation for ‘fn’:
fn (f, x) i = (fp, (f x (i + length (ns))))
• Relevant bindings include
x :: a1 (bound at t.hs:4:16)
f :: a1 -> Int -> a1 (bound at t.hs:4:13)
fn :: (a1 -> Int -> a1, a1) -> Int -> (a1 -> Int -> a1, a1)
(bound at t.hs:4:9)
ap :: a (bound at t.hs:2:11)
fp :: a -> Int -> a (bound at t.hs:2:8)
bar :: [Int] -> (a -> Int -> a) -> a -> a (bound at t.hs:2:1)
我认为功能 fp
的 bar
参数具有相同类型的 f
函数 fn
的where
子句中的函数 bar
的参数(它们都具有类型(a -> Int -> a)
),但是ghci
将其视为不同类型(a
和a1
)。
我尝试删除函数 fn
的类型签名,然后代码可以成功编译。
bar :: [Int] -> (a -> Int -> a) -> a -> a
bar ns fp ap = snd $ foldl fn (fp, ap) ns
where fn (f, x) i = (fp, (f x (i + length(ns))))
我的问题是:为什么 fn
的额外类型签名不起作用?是不是足够聪明的类型系统推断 fp
和 f
可能具有相同的类型? (尤其是 fn
在 bar
范围内时。
答案 0 :(得分:3)
a
签名中的fn
在a
的签名中未被识别为同一bar
。让这件事发挥作用的唯一方法是使用ScopedTypeVariables
。
{-# LANGUAGE ScopedTypeVariables #-}
bar :: forall a. [Int] -> (a -> Int -> a) -> a -> a
bar ns fp ap = snd $ foldl fn (fp, ap) ns
where fn :: ((a -> Int -> a), a) -> Int -> ((a -> Int -> a), a)
fn (f, x) i = (fp, (f x (i + length(ns))))
或者,你可以没有fn
的类型注释,让编译器推断它。