2009-11-30 15 views
13

Haskellのスコープがwhereの定義に問題があります。私は、xを局所的に定義された関数f1にパラメータとして明示的に使用することなく渡すために、fを持っていますが、xの型がf1の出力と互換性がないというエラーが表示されます。それは同じであるべきである。入れ子関数定義でのスコープ指定

 
f :: Eq a => a -> [a] 
f x = f1 x 
    where 
     f1 :: Eq a => a -> [a] 
     f1 y = [ x, y ] 

エラーは以下である:

 
    Couldn't match expected type `a1' against inferred type `a' 
     `a1' is a rigid type variable bound by 
      the type signature for `f1' at test.hs:4:11 
     `a' is a rigid type variable bound by 
      the type signature for `f' at test.hs:1:8 
    In the expression: x 
    In the expression: [x, y] 
    In the definition of `f1': f1 y = [x, y] 
Failed, modules loaded: none. 

I機能と、次のコードで行ったように、私はしかし、追加のパラメータとしてxを渡すと、それが正常に動作します:

 
g :: Eq a => a -> [a] 
g x = g1 x x 
    where 
     g1 :: Eq a => a -> a -> [a] 
     g1 x y = [ x, y ] 

タイプf1でタイプa(またはa1)と互換性のfaを作るための方法はありますか?

+1

非常に些細な部分を除いて、たくさんの型シグニチャを使用してコードを砂糖処理するのは非常に良い習慣ですが、私はそれらを使って局所的にスコープされた関数を砂糖砕く理由を見ません。型シグネチャが何であるかは明白です。そのような単純な関数の場合、得意先よりも読みやすさが失われます。 – Rayne

+1

実際の機能はより複雑で、私は実際の問題が明らかになるように単純な例に減らしました。 – poke

答えて

11

コードの問題は、ローカルスコープのf1タイプシグネチャです。これはローカル関数であっても、あなたは、この関数が受け取るものは何でも、F内に存在しないであろうタイプを取ることができるように、この関数を一般化してきたF1は、あらゆるタイプ

f1 :: Eq a => a -> [a]

を取ることができることを指定しますfから来るはずなので、タイプシグネチャは不要です。

f1タイプの署名を削除するだけです。

編集:私のポストを自分自身に読んでください、それは少し不明です。 a in f1は何でも取ることができるパラメータ化された型ですが、渡された引数はすでにfに束縛されています。したがって、この関数は親関数が受け取るものだけを受け取ることができます。与えられた型シグネチャはそのルールを破ります。希望はもう少し明確です。

+0

ええ、それはうまくいきます:)それでも、f1関数を明示的にタイプすることができないという誤解がありますが(私ははるかに厳しい言語から来ていますが)、何も壊れない限り、) – poke

+5

ポーク:ここでの問題は、Haskellがあなたが予想しているよりも厳密な厳密な型であることです。引数が 'Eq'型のクラスに属している可能性がありますが、コンパイラは 'f1'に渡された引数が実際に 'f'に渡されたものであることを正しく認識しました。 'f1'の型シグネチャを削除しても型の厳密さは緩和されません。そうすることで、コンパイラはあなたのために型を推論することができます。 –

13

デイブは真上です。考えてみるもう一つの方法は、両方の型シグネチャが変数aを参照していても、実際には同じ型変数ではありません。ハスケルプライム表記法では、両方の署名が、より明確にすることができるように書かれた:両方機能のために、彼らは(式内)いかなるタイプの引数を受け入れることができることを意味

forall a . Eq a => a -> [a]

。これは明らかにここでは当てはまりません。標準的なHaskell 98では、唯一の選択肢はf1の型署名を忘れることです。しかし、GHC(と他の?)はlexically scoped type variablesをサポートしています。だからあなたは書くことができる

f :: forall a. Eq a => a -> [a] 
f x = f1 x 
    where 
     f1 :: a -> [a] 
     f1 y = [ x, y ] 

そしてそれはうまくいくでしょう。

関連する問題