我目前正在尝试完全理解流。这个概念并不复杂。它就像一个列表,但尾部是thunk
而不是具体的子列表。
我可以写这样的流:
type 'a stream_t = Nil | Cons of 'a * (unit -> 'a stream_t)
let hd = function
| Nil -> failwith "hd"
| Cons (v, _) -> v
let tl = function
| Nil -> failwith "tl"
| Cons (_, g) -> g()
let rec take n = function
| Nil -> []
| Cons (_, _) when n = 0 -> []
| Cons (hd, g) -> hd::take (n-1) (g())
let rec filter f = function
| Nil -> Nil
| Cons (hd, g) ->
if f hd then Cons (hd, fun() -> filter f (g()))
else filter f (g())
到目前为止一直很好,我可以写一个简单的流:
let rec from i = Cons (i, fun() -> from (i+1))
现在,如果我被要求做一个 primes 流,我觉得非常困难。我想使用筛选算法。不考虑流,我可以轻松地做到。但对于流,我无法做到。
我搜索了代码:
(* delete multiples of p from a stream *)
let sift p = filter (fun n -> n mod p <> 0)
(* sieve of Eratosthenes *)
let rec sieve = function
| Nil -> Nil
| Cons (p, g) ->
let next = sift p (g()) in
Cons (p, fun () -> sieve next)
(* primes *)
let primes = sieve (from 2)
我几乎可以理解它正在发挥作用。但诀窍在哪里?
另外如何进行列表的排列流?