計算機科学のブログ

入門Haskell Monad型クラス HaskellのエラーとEither型 Either型 安全なsucc、tail、last関数、Maybe型、リスト、maxBound

入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)のUNIT7(実践Haskell)、LESSON38(HaskellのエラーとEither型)、38.5(練習問題)Q38-2の解答を求めてみる。

コード

safeSucc :: (Enum a, Bounded a, Eq a) => a -> Maybe a
safeSucc x | x == maxBound = Nothing
         | otherwise = Just $ succ x

safeTail :: [a] -> [a]
safeTail [] = []
safeTail (x:xs) = xs

safeLast :: [a] -> Either String a
safeLast [] = Left "空のリスト"
safeLast xs = 
    let maxLength = 10000
        safeLast' 0 _ = Left "この関数で扱えるリストの長さの上限を超えている。"
        safeLast' _ (x:[]) = Right x
        safeLast' n (x:xs) = safeLast' (n - 1) xs
    in safeLast' maxLength xs

printLast :: Show a => Either String a -> IO ()
printLast (Left x) = putStrLn x
printLast (Right x) = print x

main :: IO ()
main = do
    mapM_ print $ safeSucc <$> ([5, maxBound] :: [Int])
    mapM_ print $ safeTail <$> [[1..5], []]
    mapM_ printLast $ safeLast <$> [[1..5], [1..10001], []]

入出力結果(Terminal, Zsh)

% runghc sample2.hs
Just 6
Nothing
[2,3,4,5]
[]
5
この関数で扱えるリストの長さの上限を超えている。
空のリスト
%