昨日は、flatMap を導入する Monad 型クラスをみた。また、モナディックなチェインが値にコンテキストを与えることも確認した。Option も List も標準ライブラリに flatMap があるから、新しいコードというよりは今まであったものに対して視点を変えて見るという感じになった。あと、モナディックな演算をチェインする方法としての for 構文も確認した。
Haskell の do 記法と Scala の for 構文には微妙な違いがある。以下が do 表記の例:
foo = do
x <- Just 3
y <- Just "!"
Just (show x ++ y)
通常は return (show x ++ y) と書くと思うけど、最後の行がモナディックな値であることを強調するために Just を書き出した。一方 Scala はこうだ:
scala> def foo = for {
x <- 3.some
y <- "!".some
} yield x.shows + y
ほぼ同じに見えるけど、Scala の x.shows + y は素の String で、yield が強制的にその値をコンテキストに入れている。これは生の値があればうまくいく。だけど、モナディックな値を返す関数があった場合はどうすればいいだろう?
in3 start = do
first <- moveKnight start
second <- moveKnight first
moveKnight second
これは Scala では moveKnight second の値を抽出して yield で再包装せずには書くことができない。
def in3: List[KnightPos] = for {
first <- move
second <- first.move
third <- second.move
} yield third
この違いにより問題が生じることは実際には無いかもしれないけど、一応覚えておいたほうがいいと思う。