Ambiguous type variable `a0′ arising from a use of `getFromInt’ prevents the constraint `(GetFromIntable a0)’ from being solved. というエラーがでる

投稿者: Anonymous

type classの学習のために、かなり人工的ですが下記のようなコードを書いてみたところ、Showable, Changeableは機能しているのですが、GetFromIntableが機能していないようでエラーになりました。

コード

data Color = Red | Green

class Showable a where
  myshow :: a -> String

class Changeable a where
  change :: a -> a
  
class GetFromIntable a where
  getFromInt :: Int -> a
 
instance Showable Color where
  myshow Red = "AKA"
  myshow Green = "MIDORI"

instance Changeable Color where
  change Red = Green
  change Green = Red
  
instance GetFromIntable Color where
  getFromInt 1 = Red
  getFromInt 2 = Green

romajiRed = myshow Red
changedRomajiColor = myshow $ change Red
color = myshow $ getFromInt 1

main = do print $ romajiRed
          print $ changedRomajiColor
          print $ color

実行結果

% docker run -it --rm --name bar-haskell -v "$PWD":/tmp -w /tmp haskell:8 runghc Bar.hs

Bar.hs:26:9: error:
    * Ambiguous type variable `a0' arising from a use of `myshow'
      prevents the constraint `(Showable a0)' from being solved.
      Probable fix: use a type annotation to specify what `a0' should be.
      These potential instance exist:
        instance Showable Color -- Defined at Bar.hs:12:10
    * In the expression: myshow $ getFromInt 1
      In an equation for `color': color = myshow $ getFromInt 1
   |
26 | color = myshow $ getFromInt 1
   |         ^^^^^^^^^^^^^^^^^^^^^

Bar.hs:26:18: error:
    * Ambiguous type variable `a0' arising from a use of `getFromInt'
      prevents the constraint `(GetFromIntable a0)' from being solved.
      Probable fix: use a type annotation to specify what `a0' should be.
      These potential instance exist:
        instance GetFromIntable Color -- Defined at Bar.hs:20:10
    * In the second argument of `($)', namely `getFromInt 1'
      In the expression: myshow $ getFromInt 1
      In an equation for `color': color = myshow $ getFromInt 1
   |
26 | color = myshow $ getFromInt 1
   |                  ^^^^^^^^^^^^

コードの説明

  • Showable
    • myshowを実装することを要求する
    • Colorでは色に応じたローマ字を生成して返す(RedならAKA, GreenならMIDORI)
  • Changeable
    • changeを実装することを要求する
    • ColorではRedとGreenを入れ替える処理として実装
  • GetFromIntable
    • getFromIntを実装することを要求する
    • Colorでは1のときRed, 2のときGreenを返す処理として実装

うまくいく例

type classを用いずに下記のようにすると

f 1 = Red
color = myshow $ f 1

main = do print $ romajiRed
          print $ changedRomajiColor
          print $ color

ちゃんと実行されました。なぜ、type classだとエラーになっているのでしょう?

% docker run -it --rm --name bar-haskell -v "$PWD":/tmp -w /tmp haskell:8 runghc Bar.hs
"AKA"
"MIDORI"
"AKA"

解決

getFromIntInt を受け取って,GetFromIntable な何かの型 a の値を返します. myshowShowable な何かの型 a の値を受け取って,String を返します.

型の指定をせずに myshow $ getFromInt 1 を書いたとき,ここの getFromInt はなんの値を返せばよいでしょうか? GetFromIntable で, Showable ならなんでもいい,はずです.

というわけで,型推論についていえば上記のコードの型が決定できないということになり,エラーが生じています.このコードでは Color について GetFromIntableShowable のインスタンスと定義されていて,これが我々の意図ですが,まさにそうであることはコンパイラに教えてあげる必要があります.ほかの,たとえば changedRomajiColor = myshow $ change Red については,Red の存在によって順に型が一意にきまり,こうした問題は生じません.

解決はエラーメッセージに書いてあるとおり

Probable fix: use a type annotation to specify what `a0′ should be.

ということで,アノテーションをつけてやればよいです(エラーメッセージには instance Showable Color の存在も指摘されており,親切です).

具体的には、次のようにgetFromIntに型注釈を付けましょう:

color = myshow (getFromInt 1 :: Color)
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *