top page > computer > haskell > web_lecture > for_programmer > either_def.html
更新日:
文責: 重城良国

Either型

はじめに

Either型はPreludeで定義されている。

どういう型か

Either型は型引数を2つとる。2つの型の値のどちらかを保持する値の型を作る。値構築子LeftとRightがありそれぞれの型の値を保持する。

使用例

問題定義

あるサービスではユーザを特定するのに文字列または数値を使っているとする。たとえば以下のようになっているとする。

このサービスには山田良男さんという同姓同名の人が2人いる。その2人と小池恵子さんのIDは文字列である。山背達也さんと花中島サトルさんはIDに数値が使われている。このようなときにEither型を使うことができる。IDから名前を検索する関数を作成する。

IDを表す型は

Either Int String

とし、IDと名前を対応づける辞書は

[(Either Int String, String)]

とする。Either Int Stringを毎回書くのも大変なので型シノニムを定義する。

type Id = Either Int String

すると辞書の型は

[(Id, String)]

となる。この辞書をIDで検索する関数の型は

Id -> [(Id, String)] -> Maybe String

となる。

関数

IDから名前を求めるには関数lookupが使える。

name :: Id -> [(Id, String)] -> Maybe String
name i t = lookup i t

仮引数tが消せる。

name i = lookup i

仮引数iも消せる。結果として

name :: Id -> [(Id, String)] -> Maybe String
name = lookup

となる。関数nameは関数lookupだ。ただし関数nameはlookupよりも型が限定されている。関数nameはlookupで完全に置き換えられる。それでも関数nameを用意するのはインターフェースを明示するという意味で良いことだ。

上で挙げた例を辞書として定義する。

users :: [(Id, String)]
users = [
(Right "yoshio", "Yoshio Yamada")
(Right "yoshio2", "Yoshio Yamada")
(Left 4492, "Tatsuya Yamashiro")
(Right "keiko", "Keiko Koike")
(Left 8855, "Satoru Hananakajima") ]

% ghci users.hs
*Main> name (Right "yoshio") users
"Yoshio Yamada"
*Main> name (Left 4492) users
"Tatsuya Yamashiro"

定義

Either型も普通の代数的データ型だ。

data Either' a b = Left' a | Right' b deriving Show

関数either

動作

Either型の値がLeftかRightかによって適用する関数を選ぶ。数値ならば0かどうかを文字列ならば空文字列かどうかを調べるには

*Main> either (== 0) null $ Left 0
True
*Main> either (== 0) null $ Right ""
True

のようにする。

定義

第1引数はLeft値の中身に適用する関数で第2引数はRight値の中身に適用する関数だ。両者の返り値は同じ型であり全体の返り値となる。

either' :: (a -> c) -> (b -> c) -> Either a b -> c

Left値ならば第1引数の関数をRight値ならば第2引数の関数を適用する。

either' f _ (Left x) = f x
either' _ g (Right y) = g y

*Main> either' (== 0) null $ Left' 0
True
*Main> either' (== 0) null $ Right' 0
True

まとめ

2つの型のどちらかの値を保持する型Eitherの動作、定義について学んだ。これも多相的な型の例だ。

「Maybe型」へもどる 「再帰的な型」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics