긴 리스트에 foldl (+) 0을 돌리는 것은 내가 아는 가장 작은 공간 누수이고, 산술보다는 합성의 문제에 가깝다. 단계마다 (acc + x) 썽크가 만들어지는데 끝까지 아무도 강제하지 않으니 누산기가 리스트 길이만 한 사슬로 자란다. Data.List의 foldl'은 매 단계 누산기를 약한 머리 정규형까지 강제하므로 사슬이 생기지 않는다.
함정은 두 버전의 타입이 같다는 점이다. foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b 어디에도 결과가 요구되기 전까지 메모리를 얼마나 붙잡는지는 적혀 있지 않다. 이 fold를 보기 좋은 조합자로 감싸면 엄격성 결정은 한 단계 더 깊이 묻히고, 읽는 사람 눈에서 사라진다.
최적화를 켜면 GHC의 엄격성 분석이 그냥 foldl도 자주 구해 준다. 그래서 GHCi에서 처음 터질 때 더 당황스럽다.
더 나쁜 것은 foldl'도 WHNF까지만 간다는 점이다. (sum, count) 쌍을 누적하면 쌍 생성자만 평가되고 두 필드는 여전히 게으르다. 엄격한 필드나 구성 요소에 대한 뱅 패턴이 필요하다.
그래서 엄격성을 최적화 세부 사항으로 보지 않게 됐다. fold를 하는 조합자라면 엄격성은 이름이나 문서에, 타입 바로 옆에 있어야 한다.