Project Euler 40

http://projecteuler.net/index.php?section=problems&id=40


遅延評価を使うと簡単です。

(fun k -> k <= N)

このラムダは、こう書けます。

((>=) N)

これは、(>=)は2つの引数を取る関数とみなせて、

(>=) N k

で、

N >= k

と同じになります。これをカリー化して上のようになります。
また、関数の合成というのがあって、例えば、1を足して2倍する、というのを分解して、

let f x = x + 1
let g x = x * x

これを次のように合成します。

let h = f >> g
printfn "%d" (h 1)   // 4

左から右にデータが流れるイメージです。
そうすると、

(fun x -> fst x = k)

は、

(fst >> ((=) k))

となります。ちょっとやりすぎですね。

open Seq

let rec digits n = if n = 0 then [] else (digits (n / 10)) @ [n % 10]
let count n = initInfinite ((+) 1)

let s = seq {
   for n in count 1 do
      for d in digits n -> d
}

let d k = snd (head (filter (fst >> ((=) k)) (zip (count 1) s)))
let N = 1000000
let seq_pow = takeWhile ((>=) N) (unfold (fun k -> Some(k, k * 10)) 1)
printfn "%d" (fold (*) 1 (map d seq_pow))