70037


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

## コード

[code]

    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
    
[/code]

## 実行結果

[code]

    % 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
       |                  ^^^^^^^^^^^^
    
[/code]

### コードの説明

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

## うまくいく例

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

[code]

    f 1 = Red
    color = myshow $ f 1
    
    main = do print $ romajiRed
              print $ changedRomajiColor
              print $ color
    
[/code]

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

[code]

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


CC BY-SA 4.0
2020-08-31T13:56:33.757
70022
2020-09-01T07:19:49.950
2020-09-01T06:22:50.007
8007
9008
question
haskell
Ambiguous type variable `a0' arising from a use of `getFromInt' prevents the constraint `(GetFromIntable a0)' from being solved. というエラーがでる


`getFromInt` は `Int` を受け取って，`GetFromIntable` な何かの型 `a` の値を返します． `myshow` は
`Showable` な何かの型 `a` の値を受け取って，`String` を返します．

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

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

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

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

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

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

[code]

    color = myshow (getFromInt 1 :: Color)
    
[/code]


CC BY-SA 4.0
2020-09-01T04:11:05.203
70037
2020-09-01T07:19:49.950
2020-09-01T07:19:49.950
8007
2901
70022
answer