刚性类型变量不匹配

时间:2016-08-12 06:42:59

标签: haskell

我有关于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将其视为不同类型(aa1)。

我尝试删除函数 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 范围内时。

1 个答案:

答案 0 :(得分:3)

a签名中的fna的签名中未被识别为同一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的类型注释,让编译器推断它。