Haskell 入門


Either モナドの使い方

Either a b

Either a b 型は a と b という2種類のデータ型を保持できる。つまり、Either 型のデータコンストラクタは Left a と Right b である。データコンストラクタ Left と Right は a と b という異なる型のデータをコンテナに保持できる。

Either 型は Maybe 型と同じように失敗する可能性のある処理の値として使う。Right b は Just b と同じ意味がある。Left "error" は Nothing と同じ働きをするが、フィールドにエラーメッセージを入れることができる。Right は正しいという意味と、Either a b の右側にあるという意味が掛けてある。

Either 型が値の関数

Either a b 型が値になる関数の例を次に示す。

Prelude> :{
Prelude| foo :: Int -> Either String Int
Prelude| foo x
Prelude|   | x > 5 = Right x
Prelude|   | otherwise = Left "error"
Prelude| :}
Prelude> foo 3
Left "error"
Prelude> foo 6
Right 6

Either モナド

Maybe 型と同じように Either 型はモナドであるので、do 記法の中でプログラムされたり、return 関数や <- 記法を使うことができる。

Prelude> do return 3 :: Either String Int
Right 3
Prelude> do x <- return 3; Left "short cut!!"; return x :: Either String Int
Left "short cut!!"

do 記法のブロックのどの段階にでも Left a が現れると、ショートカットが行われその後の処理は行われない。これは Maybe モナドの Nothing に似ているが、Either の場合は Left a で例外やエラーメッセージを保持できる。

Either 型を引数にする関数

Data.Either には Either 型を取り扱う関数が定義されている。

Prelude> :browse Data.Either
data Either a b = Left a | Right b
either :: (a -> c) -> (b -> c) -> Either a b -> c
Data.Either.isLeft :: Either a b -> Bool
Data.Either.isRight :: Either a b -> Bool
Data.Either.lefts :: [Either a b] -> [a]
Data.Either.partitionEithers :: [Either a b] -> ([a], [b])
Data.Either.rights :: [Either a b] -> [b]

上の関数のうち either 関数の型は次のようになる。

Prelude> :t either
either :: (a -> c) -> (b -> c) -> Either a b -> c

either 関数の第1引数は a 型のデータを引数とする関数であり、第2引数は b 型のデータを引数とする関数である。ただし、a 型と b 型の関数の戻り値は同じ型 c でなければならない。第3引数は Either a b 型のデータである。

either は第3の引数が Left a のときはフィールドの a に第1引数の関数を適用し、Right b のときは第2引数の関数を適用する。これによって、Left a の場合と Right b の場合の処理を使い分けることができる。

Prelude> s = Left "foo" :: Either String Int
Prelude> n = Right 3 :: Either String Int
Prelude> either length (*2) s
3
Prelude> either length (*2) n
6

Either 型はパーサのような処理が失敗するかもしれないプログラムに活用されている。