2012-01-13 14 views
4

どちらかの型(おそらく2つの異なる型によってパラメータ化されています)をとり、Rightを取得する場合はLeftを取得し、別の場合を実行する単純な関数を作成しようとしました。次のコードは、一種の単純な多型に使用できますか?

someFunc :: (Show a, Show b) => Either a b -> IO() 
someFunc (Left x) = print $ "Left " ++ show x 
someFunc (Right x) = print $ "Right " ++ show x 

main = do 
    someFunc (Left "Test1") 
    someFunc (Right "Test2") 

しかし、これは私がLeft xで関数を呼び出すとき、それはdoesnのため、それが不平を言っている、

Ambiguous type variable `b0' in the constraint: 
     (Show b0) arising from a use of `someFunc' 
    Probable fix: add a type signature that fixes these type variable(s) 
    In a stmt of a 'do' expression: someFunc (Left "Test1") 

と私が正しく理解していれば

Ambiguous type variable `a0' in the constraint: 
     (Show a0) arising from a use of `someFunc' 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the expression: someFunc (Right "Test2") 

を与えますRight xの種類を知りません。またその逆もあります。ただし、この関数の分岐は使用されません。これを行うより良い方法はありますか?

答えて

3

これは、あなたがしようとしていることに大きく依存していますか?既にわかっているように、Leftコンストラクタを使用するには、構築する型を知る必要があります。フルタイプの場合はabの両方の情報が必要です。

ハスケルで多形性を達成するためのより良い方法は、型クラスを使用することです。さまざまなインスタンスに対して「メソッド」のさまざまな実装を簡単に提供できます。

オブジェクト指向とタイプクラスの両方の概念の比較は、hereです。

5

は、明示的に他のタイプを指定することによって、この作業を行うことができます。

main = do 
    someFunc (Left "Test1" :: Either String()) 
    someFunc (Right "Test2" :: Either() String) 

が、私は、これはおそらく、あなたがやろうとしているものは何でもするための最良の方法ではないことx13nに同意します。あなたがEitherの構造から派生する唯一の情報は、それがLeftRightのかどうかであるため、someFunc

someFunc :: (Show a) => Bool -> a -> IO() 
someFunc False x = print $ "Left " ++ show x 
someFunc True x = print $ "Right " ++ show x 

と機能的に同一であることに注意してください。このバージョンでは、プレースホルダータイプを指定する必要はありません。

+0

質問によれば、「どちらか」の使用の意図は**多形性**の形を得ることでした。あなたが提供しているboolean-tagの代替手段はそれをしません。 「左」と「右」の選択肢も、2つのタイプの中から選択することになっています。 –

+0

@サクンチム:私の 'someFunc'の呼び出しパターンは、質問の' someFunc'と同じです。意図が何であっても、私の定義は達成されたものです。それが何が望ましいのではない場合、それは元のソリューションの問題も指摘しています:) – ehird

5

これは良い考えです。なぜ、ハスケルがこのように振る舞うか考えていたからです。

class PseudoArbitrary a where 
    arb :: a 

instance PseudoArbitrary Int where 
    arb = 4 

instance PseudoArbitrary Char where 
    arb = 'd' 

instance PseudoArbitrary Bool where 
    arb = True 

reallyDumbFunc :: (PseudoArbitrary a, PseudoArbitrary b) => 
        Either a b -> Either a b 
reallyDumbFunc (Left x) = Right arb 
reallyDumbFunc (Right x) = Left arb 

ですので、これを確認してください。私は型クラスPseudoArbitraryを作りました。型クラスのインスタンスは型の任意の擬似要素を提供します。今私はそれを入力bの(擬似)任意の値、およびその逆で、両方abPseudoArbitraryインスタンスを有し、Leftを入れた場合、私はRightを生成Either a bをとるreallyDumbFuncションを有します。さあ、ghciで遊ぼう:

ghci> reallyDumbFunc (Left 'z') 
Ambiguous type variable blah blah blah 
ghci> reallyDumbFunc (Left 'z' :: Either Char Char) 
Right 'd' 
ghci> reallyDumbFunc (Left 'z' :: Either Char Int) 
Right 4 

Whoa!私が変更したのはタイプの入力でしたが、出力のタイプと値が完全に変更されました!これは、Haskellがそれ自身であいまいさを解決することができない理由です。それは、あなたがreallyDumbFuncのようなことをしていないことを確認するためにあなたの関数を複雑な方法で分析する必要があるからです。

関連する問題