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-of-bool (or (hk-truthy? lv) (hk-truthy? rv))))
|
||||||
((= op ":") (hk-mk-cons lv rv))
|
((= op ":") (hk-mk-cons lv rv))
|
||||||
((= op "++") (hk-list-append 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))))))
|
(:else (raise (str "unknown operator: " op))))))
|
||||||
|
|
||||||
(define
|
(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 "||" (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)
|
(hk-load-into! env hk-prelude-src)
|
||||||
env)))
|
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