2016-08-12 43 views
1

私はCouldn't match type ‘a’ with ‘a1’エラーで失敗しましたHaskellコードを次ています不一致

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 :: [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)))) 

ここでは詳細なエラーメッセージですbarがfのfパラメータの同じタイプを有します慰め機能bar(彼らはすべてのタイプ(a -> Int -> a)を持っている)のwhere句にfnは、しかし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

- それ以外の場合は2型シグネチャは両方とも' 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のために型注釈を持っていると、コンパイラはそれを推測させることができません。あなたは `ScopedTypeVariables`を有効(および型シグネチャにforallを明示的に追加)する必要が