fugafuga.write

日々のログ



すごいH本 part40

型コンストラクタの話

data Maybe a = Nothing | Just a 

aが型引数でMaybeは型コンストラクタという。型コンストラクタからMaybe Int, Maybe Char, Maybe Stringなどの型を作ることができる。

Haskell には型推論があるので、たいてい明示的に型コンストラクタに型引数を渡さなくてもよい。

*Main Lib> :t Just 'a'
Just 'a' :: Maybe Char
*Main Lib> :t Just 3
Just 3 :: Num a => Maybe a
*Main Lib> :t Just [1,2,3]
Just [1,2,3] :: Num t => Maybe [t]

明示的に型引数を渡す場合は、::をつける

*Main Lib> Just 10 :: Maybe Int
Just 10
*Main Lib> Just 10 :: Maybe Double
Just 10.0

NothingMaybe a型となるので、引数に Maybe Intを取る関数があればNothingを渡すことができる。

どういう場合に型引数をとるのがよいか

ある型がなんらかの箱のように振る舞うなら、型引数をつかうとよい。

data Car = Car { company :: String
               , model :: String
               , year :: Int
               } deriving (Show)

これに型引数を使うとこうなる

data Car a b c = Car { company :: a
                     , model :: b
                     , year :: c
                     } deriving (Show)

しかし、メリットはあまりない。

自動車の情報を表示する関数

tellCar :: Car -> String
tellCar (Car {company = c, model = m, year = y}) = 
    "This " ++ c ++ " " ++ m ++ " was made in " ++ show y

実行結果

*Main> let stang = Car {company="Ford", model="Mustang", year=1967}
*Main> tellCar stang
"This Ford Mustang was made in 1967"

型引数有りで書くとこうなる

tellCar :: (Show a) => Car String String a -> String
tellCar (Car {company = c, model = m, year = y}) =
    "This " ++ c ++ " " ++ m ++ " was made in " ++ show y

実行結果

*Main> tellCar (Car "Ford" "Mustang" 1967)
"This Ford Mustang was made in 1967"
*Main> tellCar (Car "Ford" "Mustang" "nineteen sixty seven")
"This Ford Mustang was made in \"nineteen sixty seven\""

cになんの型でもとれるようになったぐらいしかメリットがない。

このように自動車の型を多相的に表現してもあまり有用ではない。型引数を使うのは、データ型の値コンストラクタに収納された型がデータ型自体の動作にそこまで重要な影響を与えない時。

例えば、リスト型、Maybe型のように値自体がなんであってもその型が機能できるような場合に有用とのこと。

また、データ型宣言には型クラス制約を書かない。なぜなら、データ型宣言時に書いても関数の型宣言時に再び書く必要があるため。(データ宣言に型クラス制約を付ける機能自体が無くなっているはず)

所感

型引数を使うのはどのような場合かが判明した。

[asin:B009RO80XY:detail]