読者です 読者をやめる 読者になる 読者になる

IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Monadの練習

Int型の数値の確認

Prelude> 1
1
Prelude> :t 1
1 :: Num a => a

Int型の配列の型の確認

Prelude> :t [1]
[1] :: Num t => [t]

Maybe Int型の型の確認

Prelude> :t Just 1
Just 1 :: Num a => Maybe a

returnしたときの型の確認 このでは何のMonadであるかはわからない。Int型のデータを持つなんらかのMonad

Prelude> :t return 1
return 1 :: (Monad m, Num a) => m a

returnしたときに型を明示的に指定する。 Numは型クラスなので、Numの配列(?)はエラーとなる。 Int型の配列がreturnできる。

Prelude> :t return 1 :: [Num]

<interactive>:1:14:
    Expecting one more argument to `Num'
    In an expression type signature: [Num]
    In the expression: return 1 :: [Num]
Prelude> :t return 1 :: [Int]
return 1 :: [Int] :: [Int]

returnにてMaybe Int型を明示的に指定する。

Prelude> :t return 1 :: Maybe Int
return 1 :: Maybe Int :: Maybe Int

配列モナドのバインドの練習

Prelude>  (return 1 :: [Int]) >>= (\x -> [x*2])
[2]
Prelude>  (return 1 :: [Int]) >>= (\x -> [x*4])
[4]
Prelude>  (return 1 :: [Int]) >>= (\x -> [x*4]) >>= (\x -> [x + 3])
[7]
Prelude>  (return 1) >>= (\x -> [x*4]) >>= (\x -> [x + 3])
[7]

Maybeモナドのバインドの練習

Prelude>  (return 1) >>= (\x -> Just(4*1))
Just 4
Prelude>  (return 1) >>= (\x -> Just(4*1)) >>= (\x -> Just(x+3))
Just 7

異なるモナドはバインドできない。

Prelude>  (return 1) >>= (\x -> Just(4*1)) >>= (\x -> [x + 3])

<interactive>:29:45:
    Couldn't match type `[]' with `Maybe'
    Expected type: Maybe b0
      Actual type: [b0]
    In the expression: [x + 3]
    In the second argument of `(>>=)', namely `(\ x -> [x + 3])'
    In the expression:
      (return 1) >>= (\ x -> Just (4 * 1)) >>= (\ x -> [x + 3])

printの型の確認

Prelude> :t print "a"
print "a" :: IO ()

returnにIOモナドを明示的に指定するとエラーとなる。 returnでChar型をもつ何らかのモナドを指定しているが、型の指定は何もない(!)モナドだから。

Prelude> :t return 'a' :: IO ()

<interactive>:1:8:
    Couldn't match expected type `()' with actual type `Char'
    In the first argument of `return', namely 'a'
    In the expression: return 'a' :: IO ()

returnで何も返さなければ、型指定にIO ()はOK

Prelude> :t return ():: IO ()
return ():: IO () :: IO ()

Char型をもつIOモナドであれば、OK

Prelude> :t return 'a' :: IO Char
return 'a' :: IO Char :: IO Char

IOモナドの順次実行

Prelude> print "a" >> print "b"
"a"
"b"

IOモナドのバインド。 引数を明示的に無視する必要がある。

Prelude> print "a" >> print "b" >>= print "c"

<interactive>:52:28:
    Couldn't match expected type `() -> IO b0' with actual type `IO ()'
    In the return type of a call of `print'
    Probable cause: `print' is applied to too many arguments
    In the second argument of `(>>=)', namely `print "c"'
    In the expression: print "a" >> print "b" >>= print "c"
Prelude> :t print
print :: Show a => a -> IO ()
Prelude> print "a" >> print "b" >>= \x -> print "c"
"a"
"b"
"c"

Prelude>