練習問題 4.5.12

scanr1
に対する効率の良いプログラムを導出せよ.



tails1 :: [a] -> [[a]]
tails1 []  = []
tails1 [x] = [[x]]
tails1 xxs@(_:xs) = xxs : tails1 xs

scanr1 _ []     = []
scanr1 _ [x]    = [x]
scanr1 f (x:xs) = f x (head ys) : ys
                  where ys = scanr1 f xs 
[] の場合
     scanr1 f []
=        { scanr1 の定義 }
     (map (foldr1 f) . tails1) []
=        { . の定義 }
     map (foldr1 f) (tails1 [])
=        { tails1 の定義 }
     map (foldr1 f) []
=        { map の定義 }
     []

[x] の場合
     scanr1 f [x]
=        { scanr1 の定義 }
     (map (foldr1 f) . tails1) [x]
=        { . の定義 }
     map (foldr1 f) (tails1 [x])
=        { tails1 の定義 }
     map (foldr1 f) ([x]:[])
=        { map の定義 }
     foldr1 f [x] : map (foldr1 f) []
=        { map の定義 }
     foldr1 f [x] : []
=        { foldr1 の定義 }
     (if null [] then x else f x (foldr1 f [])) : []
=        { null [] = True だから }
     x : []
=        { リストのリテラル表記 }
     [x]

x:xs (null xs = False)の場合
     scanr1 f (x:xs)
=        { scanr1 の定義 }
     (map (foldr1 f) . tails1) (x:xs)
=        { . の定義 }
     map (foldr1 f) (tails1 (x:xs))
=        { tails1 の定義 }
     map (foldr1 f) ((x:xs):tails1 xs)
=        { map の定義 } 
     foldr1 f (x:xs) : map (foldr1 f) (tails1 xs)
=        { foldr1 の定義 }
     (if null xs then x else f x (foldr1 f xs)) : map (foldr1 f) (tails1 xs)
=        { null xs = False }
     f x (foldr1 f xs) : map (foldr1 f) (tails1 xs)
=        { 任意の g について head (map g (tails1 xs)) = g xs であるから }
     f x (head (map (foldr1 f) (tails1 xs))) : map (foldr1 f) (tails1 xs)
=        { scanr1 の定義 }
     f x (head (scanr1 f xs)) : scanr1 f xs
=        { ys = scanr1 f xs とおいて }
     f x (head ys) : ys
         where  ys = scanr1 f xs