2013-07-08 4 views
8

私はGHCでどのように強力な関数のオーバーロードがあるかを研究しています。私は、次のコードを書いている:なぜHaskellのこのタイプの注釈が必要ですか?

class F_third_arg a where 
    run_f :: (Integer, a) -> Integer 

instance F_third_arg Integer where 
    run_f (_, x) = x 

instance F_third_arg String where 
    run_f (x, _) = x 

my_fun :: (F_third_arg a) => Integer -> (a -> Integer) 
my_fun x = \a -> run_f(x, a) 

main :: IO() 
main = putStrLn $ show(((my_fun::Integer->(Integer->Integer)) 5) $ 6) 

は(はい、私は-XTypeSynonymInstances -XFlexibleInstancesを必要とする)と、コンパイラがmy_funへの呼び出しの近くに型注釈が必要であることを、私は驚きました。これは2つの数字に適用されます - このアノテーションを推測することで何が問題になりますか?これらの2つの拡張機能をオンにして、オーバーロードのルールは何ですか?

+0

'FlexibleInstances'は既に' TypeSynonymInstances'を意味しています。 'putStrLn。 show'は 'print'と同じです。そして、あなたはかなり多くの括弧を省略することができます... – leftaroundabout

+3

** defaulting **については(もちろん、コンパイラは_infer_型ではありません:数値リテラルは多相です!)、私はそれについての専門家ではありません。しかし、GHCの拡張デフォルトルールがその仕事をします( '{ - #LANGUAGE ExtendedDefaultRules# - }'かGHCi)。より良い方法は 'print $ my_fun 5(6 :: Integer)'です。 – leftaroundabout

+0

ありがとう!あなたのコメントは本当に役に立ちます。 –

答えて

7

コードの問題は、数値リテラル自体がすでにオーバーロードされていることです。したがって、6の文字型はNum a => aであり、my_fun 5の型はF_third_arg b => b -> Integerです。したがって、型推論の間、これらの2つの型変数を統一します。しかし、それらについての他の要件は存在しないと、GHCは、ここで使用するための具体的なタイプを見つけ、適切なエラーメッセージを与えることはできません。

 
test.hs:16:26: 
    No instance for (F_third_arg a0) arising from a use of `my_fun' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance F_third_arg String -- Defined at test.hs:9:10 
     instance F_third_arg Integer -- Defined at test.hs:6:10 
    In the expression: (my_fun 5) 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

test.hs:16:38: 
    No instance for (Num a0) arising from the literal `6' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Num Double -- Defined in `GHC.Float' 
     instance Num Float -- Defined in `GHC.Float' 
     instance Integral a => Num (GHC.Real.Ratio a) 
     -- Defined in `GHC.Real' 
     ...plus three others 
    In the second argument of `($)', namely `6' 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

一つはIntegerの両方を満たしている唯一のタイプであることをコンパイラ通知ことを期待するかもしれませんこのヒューリスティックはコードを比較的脆弱にします。つまり、新しいインスタンスを追加するだけで破損します(例:F_third_arg Double)。したがって、コンパイラはコードを拒否し、問題の型を明示するように指示します。

あなたはそれを修正する方法を見つけましたが、@ leftroundaboutsの6::Integerを使用することの提案はちょっといいです。

関連する問題