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" と異なり末尾でも改行します。