fugafuga.write

日々のログ



すごいH本 part22

真・畳み込みのコーナー

無限リストを畳み込む

and 関数を foldr で実装し、foldr が無限リストを正しく処理できるのを確認していく

実装する

and' :: [Bool] -> Bool
and' xs = foldr (&&) True xs

リストが全部Trueの場合にTrueを返して欲しいので、(&&)関数を使う

(&&)の実装

(&&) :: Bool -> Bool -> Bool
True && x = x
False && _ = False

最初の引数がFalseの場合は2つ目の引数を無視する。無限リストは2つめのパターンに合致するのでリストの要素が何個あろうがFalseを返す。

実行結果

*Main> and' (repeat False)
False

Haskell は遅延評価なので、本当に必要な部分だけを計算する。 foldr は、2番目の引数を常に評価するとは限らないような2引数関数が与えられた場合、無限リストに対してもうまく動作する。

スキャン

scanl と scanr 関数は、foldl と foldr に似ているが、アキュムレータの中間状態全てをリストとして返す。

*Main> scanl (+) 0 [1,2,3,4]
[0,1,3,6,10]
*Main> scanr (+) 0 [1,2,3,4]
[10,9,7,4,0]

scanl は結果のリストの最終要素に最終の計算結果が入る。scanr はその逆。

自然数の平方根を小さいものから足していった時、1000を超えるのは何個目か

sqrtSums :: Int
sqrtSums = length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..]))) + 1

実行結果

*Main> sqrtSums
131
*Main> sum (map sqrt [1..131])
1005.0942035344083
*Main> sum (map sqrt [1..130])
993.6486803921487

所感

中置関数の実装てTrue && x = xみたいな書き方できるのね…

あと、中学校の数学からやり直したい。平方根ってなんだっけ?みたいな感じになってた。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る