2016-08-12 87 views
1

我有以下Haskell代碼失敗的Couldn't match type ‘a’ with ‘a1’錯誤:不匹配剛性類型變量

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參數f結fn在功能bar(它們都具有類型(a -> Int -> a)where子句,然而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額外的類型簽名不工作?是不是足夠智能的類型系統推斷fpf可以有相同的類型? (特別是當fnbar的範圍內)。

+1

您需要啓用'ScopedTypeVariables'(併爲類型簽名添加一個顯式全部) - 否則兩個類型簽名引用不同類型的變量,這兩個變量都恰好被命名爲'a'。 – user2407038

回答

3

fn的簽名中的abar的簽名中未被識別爲相同的a。獲得這個東西的唯一方法是使用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類型註釋,讓編譯器來推斷。