Maybe 型 と Either 型

関数が値を返さないかもしれないときには Maybe型を使います。

tList =[("Perl","Larry Wall"),("Ruby","Matz"),("C","Dennis Ritchie"),
        ("Fortran"," John Warner Backus")]

mLookup :: String -> [(String,String)] -> Maybe String
mLookup string ((key,dat):xs) | string == key = Just dat
                              | otherwise     = mLookup string xs
mLookup _ [] = Nothing

mFind :: String -> [(String,String)] -> String
mFind str ls = case mLookup str ls of
                   Just s  -> "found! :" ++ s
                   Nothing -> "not found!"

 > mFind "Perl" tList    -- => "found! :Larry Wall"
 > mFind "Haskell" tList -- => "not found!"

関数が返す型を使い分けたいときは Either 型を使います。
リストを検索して見つかったときは Right 型でその値を返し、みつからないときは Left 型で照合した回数を返しています。
この照合した回数はあまり意味のある数字ではありませんが、Windows COM のinvoke 関数は実行に成功すると0x00000000、失敗すると0x00000000以外のRESULT コードを返します。で、成功したときには実効結果、失敗したときにはRESULT コードを返すようなときに重宝です。

eLookup :: String -> [(String,String)] -> Integer -> (Either Integer String)
eLookup string ((key,dat):xs) n | string == key = Right dat
                                | otherwise     = eLookup string xs (n+1)
eLookup _ [] n = Left n

eFind :: String -> [(String,String)] -> String
eFind str ls = case eLookup str ls 0 of
                   Right s -> "found! :" ++ s
                   Left  n -> "not found : List length = " ++ show n
        
 > mFind "Ruby" tList     -- => "found! :Matz"
 > mFind "Haskell" tList  -- => "not found : List length = 5"

COM 呼び出し失敗のとき RESULT を Left で返すようにすると Left に同じ記述のあるものがいっぱい並ぶので、それを避ける withEither。
関数名 withEither は withCString, withCWString のパクリ。

withEither :: Either a b -> (b -> Either a b) -> Either a b
withEither either func = 
    case either of
        Left  a -> Left  a
        Right b -> func b
-- 第1引数が Left のときはそのままの値が返される。
> withEither (Left "hello") (\x->Right(100*x)) -- => Left  "hello"

-- 第1引数が Right のときは第1引数 の値に第2引数の関数が適用される。
> withEither (Right 123)  (\x->Right(100*x))   -- => Right 12300

-- Right のとき呼ばれる関数は Left を返しても良い。
> withEither (Right 123)  (\x->Left (100*x))   -- => Left  12300

Either型の値がRightかどうかチェックする関数。
Left にエラーを返すようにすれば気軽にエラーがあるかどうか確認しながらコードを書ける。

isEitherRight :: Either a b -> Bool
isEitherRight either  = case either of
                            Left  a -> False
                            Right b -> True