これはHaskellスペースリーク Advent Calendar 2015の8日目の記事です。 IOのコードは、普通に書けば末尾呼び出しの最適化が効く形になる。たとえば、こんな感じ: foo :: Char -> String -> IO Int foo a b = do c <- bar a b zoo b c woo c woo :: Int -> IO Int woo c = do d <- goo c return $ d + 1 foo が woo を呼び出す時は、fooのフレームを忘れてしまってよい。IOの文脈で再帰関数を書く場合も末尾再帰で十分な場合が多い。 goo :: Int -> IO () goo 0 = return () goo n = do getChar >>= putChar goo (n - 1) 残念なことに、一見末尾再帰に見えるが実はそうなっていなく