「プログラミング Haskell 第7章 高階関数」の練習問題に unfold 関数が登場しています。
unfoldr は Data.List にも登録されていますので、どのような関数なのかやってみました。
foldはリストから値を求めますが、問題で作られている unfold 関数は初期値からリストを作る関数です。そして、引数として渡すのは次の3つの関数です。
unfold (終了を判定する関数) (リストの要素を作る関数) (再帰に渡す値を作る関数)
unfold p h t x | p x = [] |otherwise = h x : unfold p h t (t x) int2bin = unfold (==0) (`mod` 2) (`div` 2) -- int2bin 256 -- > [0,0,0,0,0,0,0,0,1] map' f = unfold (==[]) (f.head) tail -- map' (+1) [0..10] -- > [1,2,3,4,5,6,7,8,9,10,11] iterate' f = unfold (const False) f f -- take 10 $ iterate' (*2) 1 -- > [2,4,8,16,32,64,128,256,512,1024] fib = [1,1]++ (unfold (const False) (\[x,y]->x+y) (\[x,y]->[y,x+y]) [1,1]) -- > take 20 $ fib -- > [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
Data.List に定義されている unfoldr で同等の関数を定義してみます。
import Data.List -- unfoldr :: (b -> Maybe (a, b)) -> b -> [a] int2bin' = unfoldr (\x -> if x==0 then Nothing else Just (x `mod` 2,x `div` 2)) -- int2bin' 256 -- > [0,0,0,0,0,0,0,0,1] map'' f = unfoldr (\x -> if x==[] then Nothing else Just ((f.head) x ,tail x )) -- map'' (+1) [0..10] -- > [1,2,3,4,5,6,7,8,9,10,11] iterate'' f = unfoldr (\x -> Just (f x ,f x )) -- take 10 $ iterate'' (*2) 1 -- > [2,4,8,16,32,64,128,256,512,1024] fib' = [1,1]++ (unfoldr (\[x,y] -> Just (x+y ,[y,x+y])) [1,1]) -- > take 20 $ fib' -- > [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]