do
記法を用いると、演算子 *>
および >>=
と同じ計算を分かりやすく書いたり、do
記法の let
を用いて変数束縛することが可能です。
参考「[Haskell] モナド 演算子 まとめ - Qiita」
参考「3.14 Do Expressions - 3 Expressions」
1. 使い方
1.1. 基本
y = do
x
意味
y = x
1.2. 値を破棄して他の値に置き換える
z = do
x
y
意味
z = x *> y
1.3. 値に関数を適用する
y = do
x' <- x
f x'
意味
y = x >>= f
y = do
C x' <- x
f x'
意味
y = x >>= f'
where
f' (C x') = f x'
f' _ = fail "Pattern match failure"
参考「[Haskell] モナドの計算を中断する - Qiita」
1.4. 変数束縛する
z = do
let y = f x
g y
意味
z = g y
where
y = f x
2. 型
do
記法はモナドであればどんな型でも扱うことができますが、1 つの do
記法の中では (let
による変数束縛を除いて) 同じモナドしか扱うことができません。
main :: IO ()
main = do
putStrLn "Foo" :: IO ()
string :: String <- getLine :: IO String
putStrLn string :: IO ()
f :: Maybe Int -> Maybe Int
f x = do
x' :: Int <- x :: Maybe Int
let y = 23 * x' :: Int
Just y :: Maybe Int
3. おまけ: String
型の値は連結されない
type String = [Char]
よりリストモナドのため、String
型に対して do
記法を使うことができますが、演算子 *>
は連結ではないため do
記法を用いても連結されません。
main :: IO ()
main = do
putStrLn $ do
"Foo"
"Bar"
"Baz"
※上記のコードを GHC で実行すると _ <- "Foo"
および _ <- "Bar"
と書くように警告が出ます。
実行結果
BazBazBazBazBazBazBazBazBaz
もし String
型の値を連結したければ do
記法は用いず従来の方法で連結します。
main :: IO ()
main = do
putStrLn
"Foo\
\Bar\
\Baz"
putStrLn
$ "Foo"
++ "Bar"
++ "Baz"
putStrLn $ concat
[ "Foo"
, "Bar"
, "Baz"
]
実行結果
FooBarBaz
FooBarBaz
FooBarBaz
import Data.List (intercalate)
main :: IO ()
main = do
putStrLn $ unwords
[ "Foo"
, "Bar"
, "Baz"
]
putStrLn $ intercalate ", "
[ "Foo"
, "Bar"
, "Baz"
]
putStrLn $ intercalate "\n"
[ "Foo"
, "Bar"
, "Baz"
]
putStrLn $ unlines
[ "Foo"
, "Bar"
, "Baz"
]
実行結果
Foo Bar Baz
Foo, Bar, Baz
Foo
Bar
Baz
Foo
Bar
Baz
※ unlines
は intercalate "\n"
と異なり末尾でも改行します。