haskellのオフサイドルールはバインドでインデントは式の継続だったんだ。
haskellのbindがよくわからない(というかレイアウト)
なぜcat6.hsを許すんだろう・・・と、研究開始!
a.txt と b.txtを結合するものをまずdo記法で書く
--:::::::::::::: --cat1.hs --:::::::::::::: main=do x<-readFile "a.txt" y<-readFile "b.txt" putStrLn (x++y)
次に 2行目を>>=とlet inで書き直す
--:::::::::::::: --cat2.hs --:::::::::::::: main = let f x = do y<-readFile "b.txt" putStrLn (x++y) in readFile "a.txt" >>= f
let中のdoも >>=とletで書き直す
--:::::::::::::: --cat3.hs --:::::::::::::: main = let f x = let g y = putStrLn (x++y) in readFile "b.txt" >>= g in readFile "a.txt" >>= f
関数gを無名関数化
--:::::::::::::: --cat4.hs --:::::::::::::: main = let f x = readFile "b.txt" >>= \y -> putStrLn (x++y) in readFile "a.txt" >>= f
関数fを無名関数化
--:::::::::::::: --cat5.hs --:::::::::::::: main =readFile "a.txt" >>= (\x -> readFile "b.txt" >>= \y -> putStrLn (x++y))
括弧をはずしてレイアウトを…あ、あれ? これでも動くぞ?
--:::::::::::::: --cat6.hs --:::::::::::::: main =readFile "a.txt" >>= \x -> readFile "b.txt" >>= \y -> putStrLn (x++y)
本来ならこんな感じのはずなのに… readFileと\yが同じラインならわかる
--:::::::::::::: --cat7.hs --:::::::::::::: main =readFile "a.txt" >>= \x -> readFile "b.txt" >>= \y -> putStrLn (x++y)
cat7だとreadFile以降が固まりとしてとらえられてるもんな。
あ、わかったたオフサイドルールってのは >>= の場合と ; の場合の固まりを同一行にかけるってことか。
このcat6の書き方は>>=がそれぞれ独立しているように見える。つまり以下
*Main> readFile "a.txt" >>= (\x->readFile "b.txt") >>= (\y->putStrLn (x++y)) <interactive>:1:63: Not in scope: `x'
よかった、やっぱエラーだよな。
*Main> readFile "a.txt" >>= \x->readFile "b.txt" >>= \y -> putStrLn (x++y) This is a.txt This is b.txt
うお、いらないんじゃん。これどういう事? >>= よりも -> の方が優先度が強いだけか
つまりこういうことか
*Main> readFile "a.txt" >>= \x->(readFile "b.txt" >>= \y->putStrLn (x++y)) This is a.txt This is b.txt
あ、わかったたオフサイドルールってのは >>= の場合と ; の場合の固まりを同一行にかけるってことか。
で、字下げは式の継続だから両方動いたんだな。
いまのところの予想
do { x<-f ; y<-g x ; h y}
が
f >>= \x -> g x >>= \y -> h y
となって セミコロン(;)が バインド(>>=)に化けているようにみなせている まあ λ式の->の意味がって、これが代入のように見えるのがそもそも自分がわからなかった原因なんだけどw
で、セミコロンで並べて見せたいが為に 式の継続では以下のように表されるところを
f >>= \x -> g x >>= \y -> g y
オフサイドルールってのを作ったんだ。
f >>= \x -> g x >>= \y -> h y
というのを許可し、式の継続なら以下のように書くべきdo構文を
do x <- f y <- g x h y
以下のようにオフサイドルールを認めて手続き言語っぽくかけるようにしていることが…
do x <- f y <- g x h y
自分のIOモナドの理解を阻害していたことがわかったorz
てか、>>= だけで IOモナドを記述しててくれれば…(入力が一系統であれじゃわからん)
てか
main=do{x<-readFile "a.txt";y<-readFile "b.txt";putStrLn (x++y)}
これなんか 思いっきり xとyに代入されているようにみえるよ! あ、なんだかセミコロンがバインド(>>=)に見えるようになってきた…