2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Haskell] do 記法の使い方と型

Posted at

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

参考「fail - Control.Monad

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

unlinesintercalate "\n" と異なり末尾でも改行します。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?