「入門Haskell―はじめて学ぶ関数型言語」 p.86 より。昨日より1ページ戻ったけど。
(1) repeat,cycle,iterate をそれぞれ自分で定義しなさい。
これは簡単。再帰を使ってこうだ。
myRepeat a = a:map id (myRepeat a) myCycle a = a ++ myCycle a myIterate f a = a:map f (myIterate f a)
結果は省略。
(2) repeat,cycle,iterate のうち,どれか1つを自分で定義し,残りの2つはその定義した関数をもとに定義しなさい。ほかの Prelude 関数を使ってもかまいません。
こっちはちょっと難しい。とくに iterate でかなりつまった。
まずは repeat を使って他の2つを定義。
myCycle2 = (foldr (++) []) . myRepeat myIterate2 f a = map (\x -> x a) (rep f) where rep = (scanl (.) id) . myRepeat
結果。
*Main> take 50 $ myCycle "abc" "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcab" *Main> take 50 $ myIterate2 (+1) 1 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,3 0,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50]
よし,うまくいってるみたいだ。myCycle2 はこないだ覚えた foldr で無限リスト。
myIterate2 のほうは,myRepeat で関数 f のリストを作っておいて,scanl1 で合成している。これで [id, f, (f . f), (f . f . f), …] というふうなリストができる。かなりトリッキーな気がするけど,いいんだろうか。ま,結果はうまくいってるみたいだけど。
myCycle を使って他の2つを定義。
myRepeat3 a = myCycle [a] myIterate3 f a = map (\x -> x a) (cyc f) where cyc g = scanl (.) id (myCycle [g])
myRepeat3 は大した工夫ではなし,それができればあとは myIterate3 は上の myIterate2 とおなじ。
*Main> take 50 $ myRepeat3 'a' "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" *Main> take 50 $ myIterate3 (+1) 1 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,3 0,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50]
最後。myIterate を使って。
myRepeat4 = myIterate id myCycle4 = (foldr (++) []) . (myIterate id)
*Main> take 50 $ myRepeat4 'a' "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" *Main> take 50 $ myCycle4 "abc" "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcab"
追記:
myCycle2 と myCycle4 は foldr じゃなくて concat を使った方が簡単だな。
myCycle2 = concat . myRepeat myCycle4 = concat . (myIterate id)
myIterate f a = scanl (flip ($)) a (repeat f) でどでしょ