Workshop/StartHaskell2/exercise5
『高階関数』 練習問題
部分適用された関数の型
以下の式の型はなんですか。
ヒント: それぞれの関数の型は以下のとおり
コラッツ数列
コラッツ数列を返す関数を実装してみよう。
与えられた数nに、以下の操作を繰り返し適用して、数列を生成する。
- nが偶数なら、n/2 を返す
- nが奇数なら、2*n+1 を返す
たとえば 13 から始めた場合、以下のような数列が得られる。
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
このような数列(コラッツ数列)は、最終的には必ず1にたどり着くと予想されているが、未解決問題となっている。 コラッツ問題 Wikipedia
コラッツ数列を返す関数を実装してみよう。
実行例
1 から 100 までの数で、コラッツ数列がもっとも長いものは何ですか。
関数適用と関数合成
以下の関数の括弧を、関数適用($)で書き換えてみよう。(p.83, p.84)
g :: [a] -> [a]
g xs = tail (tail (tail (tail xs)))
f :: [Int] -> [Int]
f xs = take 10 (map (*3) (filter even xs))
sqrtSums :: Int
sqrtSum = length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..]))) + 1
同じものを関数合成(.)を使って書き直してみよう。
ポイントフリースタイル
以下の関数をポイントフリースタイルで書き直してみよう。 (p.87)
f :: Int -> Int
f n = 2*n + 1
g :: Int -> Int -> Int
g n m = 2*n + m
h :: Int -> [a] -> [a]
h n xs = fst (splitAt n xs)
i :: (a,a) -> [a]
i (x,y) = [x,y]
j :: (a,a,a) -> [a]
j (x,y,z) = [x,y,z]
applyTwice
applyTwice は、以下のような関数でした。(p65)
例えば、以下のように使えます。
さて、以下の式は、なにを返しますか? それはなぜですか?
applyTwice applyTwice (+1) 0
applyTwice applyTwice applyTwice (+1) 0
applyTwice applyTwice applyTwice applyTwice (+1) 0
また、以下の式を計算しようとすると、おそらく返ってきません。(Ctrl + c で中断)
それはなぜですか? この式が計算できたとしたら、その値はいくつだと考えられますか?
fold
foldl と foldr を用いて、以下の2つの関数を作成しました。
これらの関数の型はどうなりますか? foldl や foldr はどうでしたか?
これらの関数は、どのように動きますか?
これらの関数は、無限リストに対しても使えますか?
zipWith, scanl と、あの数列
次の2つの無限リストは、どのような数列を表しますか? なぜそのようになりますか?