Qiita Teams that are logged in
You are not logged in to any team

Community
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@7shi

More than 5 years have passed since last update.

フィボナッチ数

【問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
``````

再実装

bind

【問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

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

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
``````
0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away