;; primes.hs — primality testing via trial division with where clauses.

(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-primes-src
  "isPrime n\n  | n < 2    = False\n  | n == 2   = True\n  | otherwise = all notDiv [2..n-1]\n  where notDiv d = n `mod` d /= 0\n\nprimes20 = filter isPrime [2..20]\n\nnextPrime n = head (filter isPrime [n+1..])\n\ncountPrimes lo hi = length (filter isPrime [lo..hi])\n")

(hk-test
  "isPrime 2 = True"
  (hk-prog-val (str hk-primes-src "r = isPrime 2\n") "r")
  (list "True"))

(hk-test
  "isPrime 3 = True"
  (hk-prog-val (str hk-primes-src "r = isPrime 3\n") "r")
  (list "True"))

(hk-test
  "isPrime 4 = False"
  (hk-prog-val (str hk-primes-src "r = isPrime 4\n") "r")
  (list "False"))

(hk-test
  "isPrime 5 = True"
  (hk-prog-val (str hk-primes-src "r = isPrime 5\n") "r")
  (list "True"))

(hk-test
  "isPrime 1 = False"
  (hk-prog-val (str hk-primes-src "r = isPrime 1\n") "r")
  (list "False"))

(hk-test
  "isPrime 0 = False"
  (hk-prog-val (str hk-primes-src "r = isPrime 0\n") "r")
  (list "False"))

(hk-test
  "isPrime 7 = True"
  (hk-prog-val (str hk-primes-src "r = isPrime 7\n") "r")
  (list "True"))

(hk-test
  "isPrime 9 = False"
  (hk-prog-val (str hk-primes-src "r = isPrime 9\n") "r")
  (list "False"))

(hk-test
  "isPrime 11 = True"
  (hk-prog-val (str hk-primes-src "r = isPrime 11\n") "r")
  (list "True"))

(hk-test
  "primes20 = [2,3,5,7,11,13,17,19]"
  (hk-as-list (hk-prog-val (str hk-primes-src "r = primes20\n") "r"))
  (list 2 3 5 7 11 13 17 19))

(hk-test
  "countPrimes 1 10 = 4"
  (hk-prog-val (str hk-primes-src "r = countPrimes 1 10\n") "r")
  4)

(hk-test
  "nextPrime 10 = 11"
  (hk-prog-val (str hk-primes-src "r = nextPrime 10\n") "r")
  11)

{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
