Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
138 lines
3.4 KiB
Plaintext
138 lines
3.4 KiB
Plaintext
;; Infinite structures + Prelude tests. The lazy `:` operator builds
|
|
;; cons cells with thunked head/tail so recursive list-defining
|
|
;; functions terminate when only a finite prefix is consumed.
|
|
|
|
(define
|
|
hk-prog-val
|
|
(fn
|
|
(src name)
|
|
(hk-deep-force (get (hk-eval-program (hk-core src)) name))))
|
|
|
|
(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-eval-list
|
|
(fn (src) (hk-as-list (hk-eval-expr-source src))))
|
|
|
|
;; ── Prelude basics ──
|
|
(hk-test "head of literal" (hk-eval-expr-source "head [1, 2, 3]") 1)
|
|
(hk-test
|
|
"tail of literal"
|
|
(hk-eval-list "tail [1, 2, 3]")
|
|
(list 2 3))
|
|
(hk-test "length" (hk-eval-expr-source "length [10, 20, 30, 40]") 4)
|
|
(hk-test "length empty" (hk-eval-expr-source "length []") 0)
|
|
(hk-test
|
|
"map with section"
|
|
(hk-eval-list "map (+ 1) [1, 2, 3]")
|
|
(list 2 3 4))
|
|
(hk-test
|
|
"filter"
|
|
(hk-eval-list "filter (\\x -> x > 2) [1, 2, 3, 4, 5]")
|
|
(list 3 4 5))
|
|
(hk-test
|
|
"drop"
|
|
(hk-eval-list "drop 2 [10, 20, 30, 40]")
|
|
(list 30 40))
|
|
(hk-test "fst" (hk-eval-expr-source "fst (7, 9)") 7)
|
|
(hk-test "snd" (hk-eval-expr-source "snd (7, 9)") 9)
|
|
(hk-test
|
|
"zipWith"
|
|
(hk-eval-list "zipWith plus [1, 2, 3] [10, 20, 30]")
|
|
(list 11 22 33))
|
|
|
|
;; ── Infinite structures ──
|
|
(hk-test
|
|
"take from repeat"
|
|
(hk-eval-list "take 5 (repeat 7)")
|
|
(list 7 7 7 7 7))
|
|
(hk-test
|
|
"take 0 from repeat returns empty"
|
|
(hk-eval-list "take 0 (repeat 7)")
|
|
(list))
|
|
(hk-test
|
|
"take from iterate"
|
|
(hk-eval-list "take 5 (iterate (\\x -> x + 1) 0)")
|
|
(list 0 1 2 3 4))
|
|
(hk-test
|
|
"iterate with multiplication"
|
|
(hk-eval-list "take 4 (iterate (\\x -> x * 2) 1)")
|
|
(list 1 2 4 8))
|
|
(hk-test
|
|
"head of repeat"
|
|
(hk-eval-expr-source "head (repeat 99)")
|
|
99)
|
|
|
|
;; ── Fibonacci stream ──
|
|
(hk-test
|
|
"first 10 Fibonacci numbers"
|
|
(hk-eval-list "take 10 fibs")
|
|
(list 0 1 1 2 3 5 8 13 21 34))
|
|
(hk-test
|
|
"fib at position 8"
|
|
(hk-eval-expr-source "head (drop 8 fibs)")
|
|
21)
|
|
|
|
;; ── Building infinite structures in user code ──
|
|
(hk-test
|
|
"user-defined infinite ones"
|
|
(hk-prog-val
|
|
"ones = 1 : ones\nresult = take 6 ones"
|
|
"result")
|
|
(list ":" 1 (list ":" 1 (list ":" 1 (list ":" 1 (list ":" 1 (list ":" 1 (list "[]"))))))))
|
|
|
|
(hk-test
|
|
"user-defined nats"
|
|
(hk-prog-val
|
|
"nats = naturalsFrom 1\nnaturalsFrom n = n : naturalsFrom (n + 1)\nresult = take 5 nats"
|
|
"result")
|
|
(list ":" 1 (list ":" 2 (list ":" 3 (list ":" 4 (list ":" 5 (list "[]")))))))
|
|
|
|
;; ── Range syntax ──
|
|
(hk-test
|
|
"finite range [1..5]"
|
|
(hk-eval-list "[1..5]")
|
|
(list 1 2 3 4 5))
|
|
(hk-test
|
|
"empty range when from > to"
|
|
(hk-eval-list "[10..3]")
|
|
(list))
|
|
(hk-test
|
|
"stepped range"
|
|
(hk-eval-list "[1, 3..10]")
|
|
(list 1 3 5 7 9))
|
|
(hk-test
|
|
"open range — head"
|
|
(hk-eval-expr-source "head [1..]")
|
|
1)
|
|
(hk-test
|
|
"open range — drop then head"
|
|
(hk-eval-expr-source "head (drop 99 [1..])")
|
|
100)
|
|
(hk-test
|
|
"open range — take 5"
|
|
(hk-eval-list "take 5 [10..]")
|
|
(list 10 11 12 13 14))
|
|
|
|
;; ── Composing Prelude functions ──
|
|
(hk-test
|
|
"map then filter"
|
|
(hk-eval-list
|
|
"filter (\\x -> x > 5) (map (\\x -> x * 2) [1, 2, 3, 4])")
|
|
(list 6 8))
|
|
|
|
(hk-test
|
|
"sum-via-foldless"
|
|
(hk-prog-val
|
|
"mySum [] = 0\nmySum (x:xs) = x + mySum xs\nresult = mySum (take 5 (iterate (\\x -> x + 1) 1))"
|
|
"result")
|
|
15)
|
|
|
|
{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
|