Listモナド
リストもモナドである。意外なことにリストもモナドである。
リストには要素数が0個の空リストがありうる。
これは後述するMaybe や Either における失敗の表現のようなものとも言える。
モナドだから return で値を中に入れることができる。
hoge::Int -> [Int]
hoge x = return x
main = do
print $ hoge 5
モナドだから join で一皮むくことができるが、 join で裸にはできない。
import Control.Monad
main = do
let a = [[1,2],[3,5],[5,6]]
let b = [[[1],[2]],[[3],[4]]]
let c = [1]
print $ join a
print $ join b
モナドだから fmap で中の値を関数に渡すことができる。
リストには特に map というのも用意されているが、結果は fmap と同じ。
main = do
let a = [1,2,3,4,5]
print $ fmap (*2) a
print $ map (*2) a
モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。
main = do
print $ [7] >>= replicate 3
モナドだから do構文が使える。
hoge :: [Int] -> [Int]
hoge xs = do
x <- xs
return $ x * 2
main = do
print $ hoge [1,2,3,4,5]
Maybeは成否を表現できる。成功なら Just 値、失敗なら Nothing。
1個か0個しか要素を持てないリストのようなものとも言える。
モナドだから return で値を中に入れることができる。
hoge::Int -> Maybe Int
hoge x = return x
main = do
print $ hoge 5
モナドだから join で一皮むくことができるが、 join で裸にはできない。
import Control.Monad
main = do
let a = Just(Just 5) :: Maybe (Maybe Int)
let b = Just Nothing :: Maybe (Maybe Int)
let c = Just 2
print $ join a
print $ join b
モナドだから fmap で中の値を関数に渡すことができる。
main = do
let a = Just 5
print $ fmap (*2) a
モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。
hoge :: Int -> Maybe Int
hoge x
| x >= 10 = Just (x `div` 10)
| otherwise = Nothing
main = do
print $ Just 50 >>= hoge
print $ Just 5 >>= hoge
モナドだから do構文が使える。
hoge :: Maybe Int -> Maybe Int
hoge mx = do
x <- mx
if x >= 10
then return (x `div` 10)
else Nothing
main = do
print $ hoge (Just 50)
print $ hoge (Just 5)
print $ hoge Nothing
失敗するかもしれない関数を連鎖できる。
途中で失敗した場合、その後の計算は行われず最終結果は失敗になる。
hoge :: Int -> Maybe Int
hoge x
| x >= 10 = Just (x `div` 10)
| otherwise = Nothing
main = do
print $ Just 500 >>= hoge >>= hoge
print $ Just 50 >>= hoge >>= hoge
print $ Just 5 >>= hoge >>= hoge
Eitherは成否を表現でき、失敗にも値(エラー情報)を持てる。成功なら Right 値、失敗なら Left 値。
Maybeの拡張してエラー情報を持てるようにしたようなものと言える。
モナドだから return で値を中に入れることができる。
hoge::Int -> Either String Int
hoge x = return x
main = do
print $ hoge 5
モナドだから join で一皮むくことができるが、 join で裸にはできない。
import Control.Monad
main = do
let a = Right(Right 5) :: Either String (Either String Int)
let b = Right(Left "hoge") :: Either String (Either String Int)
let c = Right 2 :: Either String Int
print $ join a
print $ join b
モナドだから fmap で中の値を関数に渡すことができる。
main = do
let a = Right 5 :: Either String Int
print $ fmap (*2) a
モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。
hoge :: Int -> Either String Int
hoge x
| x >= 10 = Right (x `div` 10)
| otherwise = Left "error"
main = do
print $ Right 50 >>= hoge
print $ Right 5 >>= hoge
モナドだから do構文が使える。
hoge :: Either String Int -> Either String Int
hoge mx = do
x <- mx
if x >= 10
then return (x `div` 10)
else Left "error"
main = do
print $ hoge (Right 50)
print $ hoge (Right 5)
print $ hoge (Left "hoge")
失敗するかもしれない関数を連鎖できる。
途中で失敗した場合、その後の計算は行われず最終結果は失敗になる。
hoge :: Int -> Either String Int
hoge x
| x >= 10 = Right (x `div` 10)
| otherwise = Left "error"
main = do
print $ Right 500 >>= hoge >>= hoge
print $ Right 50 >>= hoge >>= hoge
print $ Right 5 >>= hoge >>= hoge