エラーモナドを使ったエラー処理
ほとんど http://www.haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-Error.html#1 を写経しただけ。Error クラスのインスタンスにするのにどうすりゃいいかという話さえ分かってしまえば、あとは予想可能な例外として扱えばいいだけ。どうインスタンス化すりゃいいかがいまいち分かっていないのだけど。
import Control.Monad.Error (Error, noMsg, strMsg, throwError, catchError) data LengthError = EmptyList -- ^ リストが空 | OtherError String -- ^ その他のエラー -- ListError を Error クラスのインスタンスにする. 例外として投げられるよ -- うにするため. instance Error LengthError where noMsg = OtherError "A List Error!" strMsg s = OtherError s instance Show LengthError where show EmptyList = "The list was empty!" show (OtherError msg) = msg -- | LengthError を伴う関数の結果につかう型. type LengthMonad = Either LengthError -- | 引数が空のリストだったらエラーを返す head safeHead :: [a] -> LengthMonad a safeHead [] = throwError EmptyList safeHead (x:_) = return x -- | 引数が空のリストだったらエラーを返す tail safeTail :: [a] -> LengthMonad [a] safeTail [] = throwError EmptyList safeTail (_:xs) = return xs main = do put $ safeHead [1] put $ safeHead empty put $ safeTail [1, 2] put $ (safeTail empty `catchError` (\_ -> return [])) where put (Left e) = print e put (Right x) = print x empty :: [Int] empty = []