
【해답 예】Haskell Maybe 모나드 초입문
2022-10-04 last update
15 minutes reading 하스켈Haskell Maybe 모나드 초입문의 해답 예입니다.
피보나치 수
피보나치 수
【질문1】다음의 함수 fib
로 에러를 회피하기 위해 Maybe 모나드로 재기록해 주세요.
import Control.Applicative
fib 0 = Just 0
fib 1 = Just 1
fib n | n > 1 = (+) <$> fib (n - 2) <*> fib (n - 1)
| otherwise = Nothing
main = do
print $ fib (-1)
print $ fib 6
실행 결과Nothing
Just 8
재구성
바인드
【질문 2】 Maybe 모나드를 다루는 bind
를 구현하십시오.
(Just a) `bind` b = b a
Nothing `bind` _ = Nothing
main = do
print $ Just 1 `bind` \a -> Just $ a * 2
print $ Just 1 `bind` \a -> Nothing `bind` \b -> Just $ a * b
실행 결과Just 2
Nothing
mapMaybe
재귀
【질문 3】 mapMaybe
를 재귀로 재실장해, 방금 전의 샘플로 검증해 주세요.
import Control.Applicative
mapMaybe _ [] = []
mapMaybe f (x:xs) = case f x of
Just y -> y : mapMaybe f xs
Nothing -> mapMaybe f xs
fact 0 = Just 1
fact n | n > 0 = (n *) <$> fact (n - 1)
| otherwise = Nothing
facts n = ( map fact [n, n - 1, n - 2]
, mapMaybe fact [n, n - 1, n - 2]
)
main = do
print $ facts 3
print $ facts 2
print $ facts 1 -- cで失敗
print $ facts 0 -- bで失敗
실행 결과([Just 6,Just 2,Just 1],[6,2,1])
([Just 2,Just 1,Just 1],[2,1,1])
([Just 1,Just 1,Nothing],[1,1])
([Just 1,Nothing,Nothing],[1])
foldr
【문제 4】문제 3의 해답을 foldr
로 재작성해 주세요.
import Control.Applicative
mapMaybe f = (`foldr` []) $ \x xs -> case f x of
Just x' -> x':xs
Nothing -> xs
fact 0 = Just 1
fact n | n > 0 = (n *) <$> fact (n - 1)
| otherwise = Nothing
facts n = ( map fact [n, n - 1, n - 2]
, mapMaybe fact [n, n - 1, n - 2]
)
main = do
print $ facts 3
print $ facts 2
print $ facts 1 -- cで失敗
print $ facts 0 -- bで失敗
실행 결과([Just 6,Just 2,Just 1],[6,2,1])
([Just 2,Just 1,Just 1],[2,1,1])
([Just 1,Just 1,Nothing],[1,1])
([Just 1,Nothing,Nothing],[1])
문자열 검사
【문5】문자열s
이 「x
문자의 연속한 숫자+ y
문자의 연속한 대문자」로 구성되는지 판정하는 함수numUpper x y s
를 구현해 주세요. 성공하면 Just s
, 실패하면 Nothing
를 반환합니다. 불필요한 문자는 포함하지 않는 것으로 합니다.
import Data.Char
import Control.Monad
numUpper x y s = do
guard $ length s == x + y
guard $ length (filter isDigit $ take x s) == x
guard $ length (filter isUpper $ drop x s) == y
Just s
main = do
print $ numUpper 3 2 "123AB"
print $ numUpper 3 2 "123ABC"
print $ numUpper 3 2 "12ABC"
실행 결과Just "123AB"
Nothing
Nothing
Alternative
【문 6】문자열s
의 선두 3문자가 「숫자+대문자+소문자」또는 「대문자+소문자+소문자」로 구성되는지를 판정하는 함수check s
를 구현해 주세요. <|>
를 사용하여 성공하면 Just s
, 실패하면 Nothing
를 반환합니다. 후속 문자는 판정에 영향을 주지 않습니다.
import Data.Char
import Control.Applicative
import Control.Monad
check s = do
guard $ length s >= 3
do
guard $ isDigit $ s !! 0
guard $ isUpper $ s !! 1
<|> do
guard $ isUpper $ s !! 0
guard $ isLower $ s !! 1
guard $ isLower $ s !! 2
Just s
main = do
print $ check "1"
print $ check "2Ab"
print $ check "Abc"
print $ check "Ab1"
print $ check "1AB"
실행 결과Nothing
Just "2Ab"
Just "Abc"
Nothing
Nothing
import Control.Applicative
fib 0 = Just 0
fib 1 = Just 1
fib n | n > 1 = (+) <$> fib (n - 2) <*> fib (n - 1)
| otherwise = Nothing
main = do
print $ fib (-1)
print $ fib 6
Nothing
Just 8
바인드
【질문 2】 Maybe 모나드를 다루는
bind
를 구현하십시오.(Just a) `bind` b = b a
Nothing `bind` _ = Nothing
main = do
print $ Just 1 `bind` \a -> Just $ a * 2
print $ Just 1 `bind` \a -> Nothing `bind` \b -> Just $ a * b
실행 결과
Just 2
Nothing
mapMaybe
재귀
【질문 3】
mapMaybe
를 재귀로 재실장해, 방금 전의 샘플로 검증해 주세요.import Control.Applicative
mapMaybe _ [] = []
mapMaybe f (x:xs) = case f x of
Just y -> y : mapMaybe f xs
Nothing -> mapMaybe f xs
fact 0 = Just 1
fact n | n > 0 = (n *) <$> fact (n - 1)
| otherwise = Nothing
facts n = ( map fact [n, n - 1, n - 2]
, mapMaybe fact [n, n - 1, n - 2]
)
main = do
print $ facts 3
print $ facts 2
print $ facts 1 -- cで失敗
print $ facts 0 -- bで失敗
실행 결과
([Just 6,Just 2,Just 1],[6,2,1])
([Just 2,Just 1,Just 1],[2,1,1])
([Just 1,Just 1,Nothing],[1,1])
([Just 1,Nothing,Nothing],[1])
foldr
【문제 4】문제 3의 해답을
foldr
로 재작성해 주세요.import Control.Applicative
mapMaybe f = (`foldr` []) $ \x xs -> case f x of
Just x' -> x':xs
Nothing -> xs
fact 0 = Just 1
fact n | n > 0 = (n *) <$> fact (n - 1)
| otherwise = Nothing
facts n = ( map fact [n, n - 1, n - 2]
, mapMaybe fact [n, n - 1, n - 2]
)
main = do
print $ facts 3
print $ facts 2
print $ facts 1 -- cで失敗
print $ facts 0 -- bで失敗
실행 결과
([Just 6,Just 2,Just 1],[6,2,1])
([Just 2,Just 1,Just 1],[2,1,1])
([Just 1,Just 1,Nothing],[1,1])
([Just 1,Nothing,Nothing],[1])
문자열 검사
【문5】문자열s
이 「x
문자의 연속한 숫자+ y
문자의 연속한 대문자」로 구성되는지 판정하는 함수numUpper x y s
를 구현해 주세요. 성공하면 Just s
, 실패하면 Nothing
를 반환합니다. 불필요한 문자는 포함하지 않는 것으로 합니다.
import Data.Char
import Control.Monad
numUpper x y s = do
guard $ length s == x + y
guard $ length (filter isDigit $ take x s) == x
guard $ length (filter isUpper $ drop x s) == y
Just s
main = do
print $ numUpper 3 2 "123AB"
print $ numUpper 3 2 "123ABC"
print $ numUpper 3 2 "12ABC"
실행 결과Just "123AB"
Nothing
Nothing
Alternative
【문 6】문자열s
의 선두 3문자가 「숫자+대문자+소문자」또는 「대문자+소문자+소문자」로 구성되는지를 판정하는 함수check s
를 구현해 주세요. <|>
를 사용하여 성공하면 Just s
, 실패하면 Nothing
를 반환합니다. 후속 문자는 판정에 영향을 주지 않습니다.
import Data.Char
import Control.Applicative
import Control.Monad
check s = do
guard $ length s >= 3
do
guard $ isDigit $ s !! 0
guard $ isUpper $ s !! 1
<|> do
guard $ isUpper $ s !! 0
guard $ isLower $ s !! 1
guard $ isLower $ s !! 2
Just s
main = do
print $ check "1"
print $ check "2Ab"
print $ check "Abc"
print $ check "Ab1"
print $ check "1AB"
실행 결과Nothing
Just "2Ab"
Just "Abc"
Nothing
Nothing
import Data.Char
import Control.Monad
numUpper x y s = do
guard $ length s == x + y
guard $ length (filter isDigit $ take x s) == x
guard $ length (filter isUpper $ drop x s) == y
Just s
main = do
print $ numUpper 3 2 "123AB"
print $ numUpper 3 2 "123ABC"
print $ numUpper 3 2 "12ABC"
Just "123AB"
Nothing
Nothing
【문 6】문자열
s
의 선두 3문자가 「숫자+대문자+소문자」또는 「대문자+소문자+소문자」로 구성되는지를 판정하는 함수check s
를 구현해 주세요. <|>
를 사용하여 성공하면 Just s
, 실패하면 Nothing
를 반환합니다. 후속 문자는 판정에 영향을 주지 않습니다.import Data.Char
import Control.Applicative
import Control.Monad
check s = do
guard $ length s >= 3
do
guard $ isDigit $ s !! 0
guard $ isUpper $ s !! 1
<|> do
guard $ isUpper $ s !! 0
guard $ isLower $ s !! 1
guard $ isLower $ s !! 2
Just s
main = do
print $ check "1"
print $ check "2Ab"
print $ check "Abc"
print $ check "Ab1"
print $ check "1AB"
실행 결과
Nothing
Just "2Ab"
Just "Abc"
Nothing
Nothing