haskell: lazy sieve of Eratosthenes (+mod/div/rem/quot, +2 tests, 390/390)
This commit is contained in:
@@ -480,6 +480,10 @@
|
||||
((= op "||") (hk-of-bool (or (hk-truthy? lv) (hk-truthy? rv))))
|
||||
((= op ":") (hk-mk-cons lv rv))
|
||||
((= op "++") (hk-list-append lv rv))
|
||||
((= op "mod") (mod lv rv))
|
||||
((= op "div") (floor (/ lv rv)))
|
||||
((= op "rem") (mod lv rv))
|
||||
((= op "quot") (truncate (/ lv rv)))
|
||||
(:else (raise (str "unknown operator: " op))))))
|
||||
|
||||
(define
|
||||
@@ -670,6 +674,10 @@ plus a b = a + b
|
||||
(dict-set! env "&&" (hk-make-binop-builtin "&&" "&&"))
|
||||
(dict-set! env "||" (hk-make-binop-builtin "||" "||"))
|
||||
(dict-set! env "++" (hk-make-binop-builtin "++" "++"))
|
||||
(dict-set! env "mod" (hk-make-binop-builtin "mod" "mod"))
|
||||
(dict-set! env "div" (hk-make-binop-builtin "div" "div"))
|
||||
(dict-set! env "rem" (hk-make-binop-builtin "rem" "rem"))
|
||||
(dict-set! env "quot" (hk-make-binop-builtin "quot" "quot"))
|
||||
(hk-load-into! env hk-prelude-src)
|
||||
env)))
|
||||
|
||||
|
||||
48
lib/haskell/tests/program-sieve.sx
Normal file
48
lib/haskell/tests/program-sieve.sx
Normal file
@@ -0,0 +1,48 @@
|
||||
;; sieve.hs — lazy sieve of Eratosthenes.
|
||||
;;
|
||||
;; The canonical artefact lives at lib/haskell/tests/programs/sieve.hs.
|
||||
;; Mirrored here as an SX string because the default eval env has no
|
||||
;; read-file. Uses filter + backtick `mod` + lazy [2..] — all of which
|
||||
;; are now wired in via Phase 3 + the mod/div additions to hk-binop.
|
||||
|
||||
(define
|
||||
hk-as-list
|
||||
(fn (xs)
|
||||
(cond
|
||||
((and (list? xs) (= (first xs) "[]")) (list))
|
||||
((and (list? xs) (= (first xs) ":"))
|
||||
(cons (nth xs 1) (hk-as-list (nth xs 2))))
|
||||
(:else xs))))
|
||||
|
||||
(define
|
||||
hk-prog-val
|
||||
(fn
|
||||
(src name)
|
||||
(hk-deep-force (get (hk-eval-program (hk-core src)) name))))
|
||||
|
||||
(define
|
||||
hk-sieve-source
|
||||
"sieve (p:xs) = p : sieve (filter (\\x -> x `mod` p /= 0) xs)
|
||||
sieve [] = []
|
||||
primes = sieve [2..]
|
||||
result = take 10 primes
|
||||
")
|
||||
|
||||
(hk-test
|
||||
"sieve.hs — first 10 primes"
|
||||
(hk-as-list (hk-prog-val hk-sieve-source "result"))
|
||||
(list 2 3 5 7 11 13 17 19 23 29))
|
||||
|
||||
(hk-test
|
||||
"sieve.hs — 20th prime is 71"
|
||||
(nth
|
||||
(hk-as-list
|
||||
(hk-prog-val
|
||||
(str
|
||||
hk-sieve-source
|
||||
"result20 = take 20 primes\n")
|
||||
"result20"))
|
||||
19)
|
||||
71)
|
||||
|
||||
{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
|
||||
13
lib/haskell/tests/programs/sieve.hs
Normal file
13
lib/haskell/tests/programs/sieve.hs
Normal file
@@ -0,0 +1,13 @@
|
||||
-- sieve.hs — lazy sieve of Eratosthenes.
|
||||
--
|
||||
-- Each recursive call to `sieve` consumes one prime `p` off the front
|
||||
-- of the input stream and produces an infinite stream of composites
|
||||
-- filtered out via `filter`. Because cons is lazy, only as much of
|
||||
-- the stream is forced as demanded by `take`.
|
||||
|
||||
sieve (p:xs) = p : sieve (filter (\x -> x `mod` p /= 0) xs)
|
||||
sieve [] = []
|
||||
|
||||
primes = sieve [2..]
|
||||
|
||||
result = take 10 primes
|
||||
Reference in New Issue
Block a user