2009-04-03 14 views
6

Cabbage.hs:この型の変数があいまいなのはなぜですか?

module Cabbage where 
class Cabbage a 
    where foo :: a -> String  -- the parameter is only present for its type, 
           -- the parameter value will be ignored 
     bar :: String -> a 
quux :: Cabbage a => String -> a 
quux s = bar (s ++ foo (undefined :: a)) 

私は(GHCで)コンパイルするとき、私は、このエラーメッセージが表示されます:

Cabbage.hs:7:19: 
    Ambiguous type variable `a' in the constraint: 
     `Cabbage a' arising from a use of `foo' at Cabbage.hs:7:19-38 
    Probable fix: add a type signature that fixes these type variable(s) 

aが曖昧である理由を私は理解していません。もちろん、7行目のaは6行目のaと同じですか?これをどうやって解決するのですか?

また、インスタンス単位の定数を宣言するより良い方法がありますか?

答えて

11

スコープタイプの変数を使用すると、undefined :: aが同じである必要があることをGHCに知らせることができます(それ以外の場合は、はforall a. aの省略形です)。スコープ型変数は、FORALL修飾明示的である必要があります。

{-# LANGUAGE ScopedTypeVariables #-} 
module Cabbage where 
class Cabbage a 
    where foo :: a -> String  -- the parameter is only present for its type, 
           -- the parameter value will be ignored 
     bar :: String -> a 
quux :: forall a. Cabbage a => String -> a 
quux s = bar (s ++ foo (undefined :: a)) 
2

ハスケルはCabbageのどのインスタンスがfooに対応しているのかわかりません。

quux :: Cabbage a => String -> a 
quux s = result 
    where result = bar (s ++ foo result) 

これがfooを結びつけるとなるように一緒にバー:だから私の知る限りでは、それはaquux :: Cabbage a => String -> a

には、それはあなたが望むものだと仮定すると(undefined :: a)aと一致していない、あなたはこれを行うことができます両方に対して同じインスタンスを使用します。実際にはfooの入力値が必要ないので、それはボトムアウトします。私はインスタンスごとの定数を実行するより良い方法を知っていません。うまくいけば、他の誰かが一緒に来るだろう。

2

あなたが機能

quux :: Cabbage a => String -> a 
quux s = quux' undefined 
    where quux' :: Cabbage a => a -> a 
      quux' x = bar (s ++ foo x) 
として多型部分を抽出することができます
関連する問題