練習問題 4.6.5

⊗が結合的で単位元 e を持つなら,scanl (⊗) e は foldr の具体例として書けることを証明せよ. ⊗ および e に何の仮定もおかずに scanl (⊗) e を foldl の具体例として書けるか.


scanl (⊗) e xs = foldr g [e] xs where g x xs = e:map (x ⊗) xs であることの証明 xs 上の帰納法を使う.

[] の場合
    scanl (⊗) e []
=       { scanl の定義 }
    map (foldl f e) (inits [])
=       { initsの定義 }
    map (foldl f e) [[]]
=       { map の定義 }
    foldl f e [] : map (foldl f e) []
=       { foldl の定義,map の定義 }
    e:[]
=       { リテラル表記 }
    [e]
=       { foldr の定義 }
    foldr g [e] [] where g x xs = e : map (x ⊗) xs

x:xs の場合
左辺
    scanl (⊗) e (x:xs)
=       { scanl の定義2 }
    e : scanl (⊗) (e ⊗ x) xs
=       { e は単位元 }
    e : scanl (⊗) x xs
=       { scanlの定義 }
    e : map (foldl (⊗) x) (inits xs)
右辺
    foldr g [e] (x:xs)
=       { foldr の定義}
    g x (foldr g [e] xs)
=       { 帰納法の仮定 }
    g x (scanl (⊗) e xs)
=       { g の定義 }
    e : map (x ⊗) (scanl (⊗) e xs)
=       { scanl の定義 }
    e : map (x ⊗) (map (foldl (⊗) e) (inits xs)
=       { map は関手 }
    e : map ((x ⊗) . foldl (⊗) e) (inits xs)
=       { ⊗が結合的で単位元 e を持つなら (x ⊗) . foldl (⊗) e = foldl (⊗) x }
=   e : map (foldl (⊗) x) (inits xs)

⊗が結合的で単位元 e を持つなら (x ⊗) . foldl (⊗) e = foldl (⊗) x の証明

⊗が結合的で単位元 e を持つなら
    x ⊗ (foldl (⊗) e xs)
=       { 第1双対定理 }
    x ⊗ (foldr (⊗) e xs)
=       { foldr の定義 }
    foldr (⊗) e (x:xs)
=       { 第1双対定理 }
    foldl (⊗) e (x:xs)
=       { foldl の定義 }
    foldl (⊗) (e ⊗ x) xs
=       { e は単位元 }
    foldl (⊗) x xs

scanl を foldl のインスタンスとして定義すると

scanl (⊗) e = foldl f [e]
              where  f xs x = xs ++ [last xs ⊗ x]

となるが,とくに ⊗ および e に何の仮定もおかなくてもよい.