2012-02-04 9 views
7

私は1週間前にハスケルを勉強し始めて、奇妙な問題が1つありました。私は単純なデータ型を作成し、それをコンソールに表示したいと思っています。自分のタイプの2つのコンストラクタに対して2つの関数を作成しました。 2つの引数を持つコンストラクタを使用すると、コンパイラは関数を呼び出すことができます。しかし、1つの引数を持つコンストラクタをキャッチする別の関数を呼び出すことはできません。異なるデータコンストラクタのための関数

module Main (
    main 
) where 

data MyContainter a b = FirstVersion a b 
        | SecondVersion a 
        deriving(Show,Eq) 

showContainer (FirstVersion a b) = show b 
showContainer (SecondVersion a) = show a 

--startF = showContainer (FirstVersion 1 2) -- it works 
startF = showContainer (SecondVersion 1) -- it doesn't work 

main = putStr startF 

コンパイラは伝え:

Ambiguous type variable `a0' in the constraint: 
    (Show a0) arising from a use of `showMaybe' 
Probable fix: add a type signature that fixes these type variable(s) 
In the expression: showMaybe (SecondVersion 1) 
In an equation for `startF': startF = showMaybe (SecondVersion 1) 

なぜそれはそれを言うのでしょうか?私は(SecondVersion 1)を直接作成し、なぜコンパイラーがshowContainer(SecondVersion a)を呼び出さないのか理解していません。

showContainer :: (Show a, Show b) => MyContainer a b -> String 

しかし、あなたはSecondVersion 1を渡すとき、それは、bが何であるかを知らないのでbのあらゆるタイプのSecondVersion 1作品:

+0

エラーメッセージ中の型変数 'a0'が' b'と同じで、 'a'とは何の関係もないことを理解するのに役立ちます。 ( 'Show'クラスは' a'という名前を使っているのでコンパイラはその名前を選んでしまいました。 – hammar

答えて

9

問題はshowContainerが型を持っているということです! FirstVersionを渡すと、FirstVersionにはabの両方が含まれているため、正常に動作します。何をする必要があるかについてあいまいさはありません。だから、

、コンパイラはあなたが何をしたいb知る方法がない、とあなたはFirstVersionを渡すときbの選択がshowContainerに影響を及ぼさないことを知る方法(結局、それはが、動作には影響しないんので、タイプbの値にshowを使用しているので、それはあきらめます。

これはエラーメッセージです。タイプ変数a0 はあいまいです。タイプシグネチャを追加して、それが何であるか教えてください。この場合、それが何であるかは関係ありませんので、あなただけの()に設定することができます

startF = showContainer (SecondVersion 1 :: MyContainer Integer()) 

コンテキストはあなたが値を使用するので、あなたはおそらく、非常に多くの場合、このようなエラーに実行されません通常は特定のbを強制的に使用します。

GHCは、残念なことに型変数を選ぶ際には最適ではありません。私が示したようにshowContainerに明示的なタイプシグネチャを指定した場合は、エラーメッセージにbも使用されます。

+0

ありがとう、それは素敵な説明です) – Alexey

関連する問題