2008年10月17日金曜日

Haskell でフィールドに型変数を含んだ型の print

前回の「Haskell で代数的データ型の値を print で出力」では、型のフィールドに型変数が含まれていなかった。今回はフィールドに型変数が含まれる場合について試してみる。

 

Iremono a 型

例えば、何でも入る「入れ物」を想定し、型変数を一つフィールドに持つ `Iremono a 型’ を定義。

data Iremono a = Iremono a

これを print で出力できるようにしたい。

 

instance Show Iremono

ここで、次のように Iremono を Show クラスのインスタンスにすると、

instance Show Iremono

次のように怒られる。 (+_+)

    `Iremono' is not applied to enough type arguments
    Expected kind `*', but `Iremono' has kind `* -> *'
    In the instance declaration for `Show Iremono'

これは kind と言って、型を分類するための概念らしい。 (cf. Kind – HaskellWiki) 詳しくはわからないので横に置いておく。 ^^; QQQ

 

instance Show (Iremono a)

ところで、Show クラスのインスタンスにしたい対象は Iremono 型ではなくて Iremono a 型。( Iremono は型ではなくて、型コンストラクタ) だから次のように、

instance Show (Iremono a) where
    show (Iremono x) = "nakami ari"

main = print $ Iremono 100

上記は入れ物の中に中身がある場合に「中身あり」と表示させるようにしただけ。

 

instance Show a => (Iremono a)

しかし、普通 print と言ったら、その中身を表示させたいので、

instance Show (Iremono a) where
    show (Iremono x) = show x

これでいいのかなと思いきや、また怒られた。 (+_+)

    Could not deduce (Show a) from the context (Show (Iremono a))
      arising from a use of `show' at functest.hs:4:23-28
    Possible fix:
      add (Show a) to the context of the type signature for `show'
    In the expression: show x
    In the definition of `show': show (Iremono x) = show x
    In the definition for method `show'

deduce とか難しいことが書かれている (@_@;) けれど、ゆっくりとエラーの内容を読むと、show x の式が問題なことがわかる。show x の x と言ったら、「入れ物」の `中身’ のこと。これはどんな型でも入れることができるので、show を適用できるかどうかはわからない。だから、次のように `中身’ も Show クラスのインスタンスでないといけないことを示す必要がある。

instance Show a => Show (Iremono a) where
    show (Iremono x) = show x

 

全体を示すと、

data Iremono a = Iremono a

instance Show a => Show (Iremono a) where
    show (Iremono x) = show x

main = print $ Iremono 100

結果は、

100

 

deriving

前回教えていただいたように deriving を使うと、instance Show … を書かなくても、

data Iremono a = Iremono a deriving Show

main = print $ Iremono 100

結果は、次のように表示される。

Iremono 100

 

参考