Haskell: type と typeclass を作る (5)
前回の続き.
Learn You a Haskell for Great Good! の Chapter 8, Making Our Own Types and Typeclasses を元にしたものです.基本的には翻訳のつもりですが,省略や加筆が勝手に入ることもあります.原文は CC-BY-NC-SA でライセンスされており,この文書もそれに従います.
今回は Type synonyms から.
Type synonyms
[Char] と String って一緒で interchangeable じゃん,String があるのはそのほうが見やすい/意味が通りやすいから.たとえば
toUpperString :: [Char] -> [Char] よりは String -> String のほうがわかりやすいでしょ.
これはこういう感じで実現されている
type String = [Char]それから電話帳なんかも,この本の前のところでは
phoneBook :: [(String, String)]
phoneBook =
[
("Betty", "000-0000"),
("Richard", "111-1111")
]こんな感じで書いてたけど phoneBook :: [(String, String)] では紛らわしい.
そこで
type PhoneNumber = String
type Name = String type PhoneBook = [(Name, PhoneNumber)]とするとわかりやすいし phoneBook :: PhoneBook と出来て幸せだ.
因みに,この type synonym は本当に synonym なので,例えば s::PhoneNumber と t::String とを (++) で繋げたりするのは通る.
さて,この type synonym は例によって引数とるようにできて, 例えばこうだ
type AssociationList k v = [(k,v)]こうすると例えば getItem みたいな函数は
(Eq k) => l -> AssociationList k v -> Maybe v みたいな型を持つことになる .
実際の値が持つ型は AssociationList String Int みたいな感じ.
わかりやすそうだ.
因みにこういう芸当も可能
type IntMap v = Map Int vまあそらそうか,という感じですね.
さて,このあと原文のいろいろを飛ばしますが,recursive なデータ構造も作れるということを少し書いておきましょう.
リスト構造を模倣してみよう
data List a = Empty | Cons a (List a) deriving (Show, Read, Eq, Ord)型変数が入っていることに気をつける. この段階ではこういうふうに使えて
ghci> 3 `Cons` (4 `Cons` (5 `Cons` Empty))
Cons 3 (Cons 4 (Cons 5 Empty))いいんだけど括弧が面倒そう.演算子っぽい文字を使えば infixr , infixl で演算子としての結合度を決められる.
r のほうが右結合ということで,その後の数字は優先度だ(ghci で :i (+) とかやると色々見られるから試してみよう).
例えば * は infixl 7, + は infixl 6 ということになっている.ご存知 $ は infixr 0 だ.
こうなる
infixr 5 :-:
data List a = Empty | a :-: (List a) deriving (Show, Read, Eq, Ord)ghci> 3 :-: 4 :-: 5 :-: Empty
(:-:) 3 ((:-:) 4 ((:-:) 5 Empty))Pattern match もいい感じにできる(あれはコンストラクタを比べている1):
infixr 5 .++
(.++) :: List a -> List a -> List a
Empty .++ ys = ys
(x :-: xs) .++ ys = x :-: (xs .++ ys)このあと二分木を実装し, Typeclasses 102 に至ります.二分木は飛ばす.
–
-
Eq 配下にないものでもできるのはそういうわけだ ↩