seq関数
seq :: a -> b -> b
aとbを弱頭部正規形まで評価してから、bをそのまま返す
Haskellで正格評価したいときなどに使う
ただし、a→bの順序で評価されるとは限らない
the expression seq a b does not guarantee that a will be evaluated before b ref
これを「a→bの順で評価される」と書いてる解説ブログを何件か見かけたmrsekut.icon
docs
ghciの:sprintを使って確かめると良い
弱頭部正規形でないものを弱頭部正規形に変換する例
code:ghci(hs)
ghci> let x = 1 + 2 :: Int -- 1+2はまだ評価されていない
ghci> :sprint x
x = _ -- まだthunkのままであることを確認
ghci> seq x () -- 弱頭部正規形に簡約
()
ghci> :sprint x
x = 3 -- 簡約されている
code:ghci(hs)
-- ヘイヘイHaskell p.12
ghci> let x = 1 + 1 :: Int
ghci> let z = id (x,x+1)
ghci> :sprint z
z = _
ghci> seq z () -- 弱頭部正規形に簡約
()
ghci> :sprint z
z = (_,_) -- 中身はthunk
ghci> seq x () -- xを弱頭部正規形に簡約
()
ghci> :sprint z
z = (2,_) -- x+1の方はthunk
code:ghci(hs)
-- ヘイヘイHaskell p.13
ghci> let xs = map (+1) 1..10 :: Int
ghci> :sprint xs
xs = _
ghci> seq xs () -- 弱頭部正規形に簡約。(:)がコンストラクタ
()
ghci> :sprint xs
xs = _ : _ -- mapの定義内の f x : map f xs がthunkになっている
ghci> length xs
10
ghci> :sprint xs
xs = _,_,_,_,_,_,_,_,_,_ -- lengthの定義に因る。(f x)はthunkのまま
ghci> sum xs
65
ghci> :sprint xs
xs = 2,3,4,5,6,7,8,9,10,11
既に弱頭部正規形になっているものに適用しても何も変わらない例
code:ghci(hs)
ghci> let x = Just (1+2) :: Maybe Int -- 既に弱頭部正規形
ghci> :sprint x
x = Just _
ghci> seq x ()
()
ghci> :sprint x
x = Just _ -- seqの実行前後で変わらない
code:ghci(hs)
ghci> seq (\x -> undefined) () -- 既に弱頭部正規形なので、errorにならない
code:ghci(hs)
ghci> seq error () -- 既に弱頭部正規形なので、errorにならない
参考
/mrsekut-book-4873116899/032
https://wiki.haskell.org/Seq
/mrsekut-book-4774183903/250
https://stackoverflow.com/questions/12687392/why-is-seq-bad