【해답 예】Haskell 예외 처리 초입문

【해답 예】Haskell 예외 처리 초입문

2022-10-04 last update

11 minutes reading 하스켈
Haskell 예외 처리 초입문 의 해답 예입니다.

오류 이유



【문 1】다음 코드로 탈출의 이유( out of range , not xxx: 'X' )를 돌려주도록 수정해 주세요.
import Data.Char
import Control.Monad

getch s n
    | n < length s = Right $ s !! n
    | otherwise    = Left "out of range"

test s = do
    ch0 <- getch s 0
    ch1 <- getch s 1
    ch2 <- getch s 2
    unless (isUpper ch0) $ Left $ "not upper: " ++ show ch0
    unless (isLower ch1) $ Left $ "not lower: " ++ show ch1
    unless (isDigit ch2) $ Left $ "not digit: " ++ show ch2
    return [ch0, ch1, ch2]

main = do
    print $ test "Aa0"
    print $ test "A"
    print $ test "aa0"
    print $ test "AA0"
    print $ test "Aaa"

실행 결과
Right "Aa0"
Left "out of range"
Left "not upper: 'a'"
Left "not lower: 'A'"
Left "not digit: 'a'"

Fizz Buzz



【질문 2】다음 JavaScript의 코드를 이식해 주세요. Either 모나드를 사용하여 가능한 한 동일한 구조로 만드십시오.
import Control.Monad
import Data.Either

fizzBuzz x = either id id $ do
    when (x `mod` 3 == 0 && x `mod` 5 == 0) $ Left "FizzBuzz"
    when (x `mod` 3 == 0) $ Left "Fizz"
    when (x `mod` 5 == 0) $ Left "Buzz"
    return $ show x

main = do
    forM_ [1..15] $ \i ->
        putStrLn $ fizzBuzz i

실행 결과
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

예외



【질문 3】다음 코드는 예외가 발생해 도중에 멈추어 버립니다. 예외가 발생하면 원래 문자열을 표시하고 계속되도록 수정하십시오.
import Control.Monad
import Control.Exception

main =
    forM_ ["1", "a", "3"] $ \s ->
        print (read s :: Int)
        `catch` \(SomeException _) ->
            print s

실행 결과
1
"a"
3

try



【질문 4】 try 는 예외를 Left 로 변환하는 함수입니다. 다음 코드는 잘 작동하지 않지만 try의 동작을 확인할 수 있도록 수정하십시오.
import Control.Exception
import Control.Monad

main = do
    forM_ [0..3] $ \i -> do
        a <- try $ evaluate $ 6 `div` i
        print (a :: Either SomeException Int)

실행 결과
Left divide by zero
Right 6
Right 3
Right 2

모나드 변환기



【문 5】문 1의 해답을 StateT 모나드 변환자를 사용해 재작성해 주세요.
import Data.Char
import Control.Monad.State

getch f s = StateT getch where
    getch (x:xs)
        | f x       = Right (x, xs)
        | otherwise = Left $ "not " ++ s ++ ": " ++ show x
    getch _         = Left "out of range"

test = evalStateT $ do
    ch0 <- getch isUpper "upper"
    ch1 <- getch isLower "lower"
    ch2 <- getch isDigit "digit"
    return [ch0, ch1, ch2]

main = do
    print $ test "Aa0"
    print $ test "A"
    print $ test "aa0"
    print $ test "AA0"
    print $ test "Aaa"

실행 결과
Right "Aa0"
Left "out of range"
Left "not upper: 'a'"
Left "not lower: 'A'"
Left "not digit: 'a'"