module Spec (spec) where
import Control.Egison
import Data.Numbers.Primes
import Test.Hspec
--
-- Basic list processing functions in pattern-matching-oriented programming style
--
pmap :: (a -> b) -> [a] -> [b]
pmap f xs = matchAll xs (List Something)
[[mc| _ ++ $x : _ -> f x |]]
pmConcat :: [[a]] -> [a]
pmConcat xss = matchAll xss (Multiset (Multiset Something))
[[mc| ($x : _) : _ -> x |]]
pmUniq :: (Eq a) => [a] -> [a]
pmUniq xs = matchAll xs (List Eql)
[[mc| _ ++ $x : !(_ ++ #x : _) -> x |]]
pmIntersect :: (Eq a) => [a] -> [a] -> [a]
pmIntersect xs ys = matchAll (xs, ys) (Pair (Multiset Eql) (Multiset Eql))
[[mc| (($x : _), (#x : _)) -> x |]]
pmDiff :: (Eq a) => [a] -> [a] -> [a]
pmDiff xs ys = matchAll (xs, ys) (Pair (Multiset Eql) (Multiset Eql))
[[mc| (($x : _), !(#x : _)) -> x |]]
spec :: Spec
spec = do
describe "list and multiset matchers" $ do
it "cons pattern for list" $
matchAll [1,2,3] (List Integer) [[mc| $x : $xs -> (x, xs) |]]
`shouldBe` [(1, [2,3])]
it "multiset cons pattern" $
matchAll [1,2,3] (Multiset Integer) [[mc| $x : $xs -> (x, xs) |]]
`shouldBe` [(1,[2,3]),(2,[1,3]),(3,[1,2])]
it "join pattern for list matcher" $ length (
matchAll [1..5] (List Integer)
[[mc| $xs ++ $ys -> (xs, ys) |]])
`shouldBe` 6
it "value pattern for list matcher (1)" $
match [1,2,3] (List Integer)
[[mc| #[1,2,3] -> "Matched" |],
[mc| _ -> "Not matched" |]]
`shouldBe` "Matched"
it "value pattern for list matcher (2)" $
match [1,2,3] (List Integer)
[[mc| #[2,1,3] -> "Matched" |],
[mc| _ -> "Not matched" |]]
`shouldBe` "Not matched"
it "value pattern for multiset matcher" $
match [1,2,3] (Multiset Integer)
[[mc| #[2,1,3] -> "Matched" |],
[mc| _ -> "Not matched" |]]
`shouldBe` "Matched"
-- it "test" $
-- match 1 (List Integer)
-- [[mc| $x -> "Matched" |]]
-- `shouldBe` "Matched"
describe "match-all with infinitely many results" $ do
it "Check the order of pattern-matching results (multiset bfs) " $
take 10 (matchAll [1..] (Multiset Integer)
[[mc| $x : $y : _ -> (x, y) |]])
`shouldBe` [(1,2),(1,3),(2,1),(1,4),(2,3),(3,1),(1,5),(2,4),(3,2),(4,1)]
it "Check the order of pattern-matching results (set bfs)" $
take 10 (matchAll [1..] (Set Integer)
[[mc| $x : $y : _ -> (x, y) |]])
`shouldBe` [(1,1),(1,2),(2,1),(1,3),(2,2),(3,1),(1,4),(2,3),(3,2),(4,1)]
it "Check the order of pattern-matching results (set dfs)" $
take 10 (matchAllDFS [1..] (Set Integer)
[[mc| $x : $y : _ -> (x, y) |]])
`shouldBe` [(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9),(1,10)]
describe "built-in pattern constructs" $ do
it "Predicate patterns" $
matchAll [1..10] (Multiset Integer)
[[mc| (?(\x -> mod x 2 == 0) & $x) : _ -> x |]]
`shouldBe` [2,4,6,8,10]
describe "patterns for prime numbers" $ do
it "twin primes (p, p+2)" $
take 10 (matchAll primes (List Integer)
[[mc| _ ++ $p : #(p+2) : _ -> (p, p+2) |]])
`shouldBe` [(3,5),(5,7),(11,13),(17,19),(29,31),(41,43),(59,61),(71,73),(101,103),(107,109)]
it "prime pairs whose form is (p, p+6) -- pattern matching with infinitely many results" $
take 10 (matchAll primes (List Integer)
[[mc| _ ++ $p : _ ++ #(p+6) : _ -> (p, p+6) |]])
`shouldBe` [(5,11),(7,13),(11,17),(13,19),(17,23),(23,29),(31,37),(37,43),(41,47),(47,53)]
it "prime triplets -- and-patterns, or-patterns, and not-patterns" $
take 10 (matchAll primes (List Integer)
[[mc| _ ++ $p : ($m & (#(p+2) | #(p+4))) : #(p+6) : _ -> (p, m, p+6) |]])
`shouldBe` [(5,7,11),(7,11,13),(11,13,17),(13,17,19),(17,19,23),(37,41,43),(41,43,47),(67,71,73),(97,101,103),(101,103,107)]
describe "Basic list processing functions" $ do
it "map" $
pmap (+ 10) [1,2,3] `shouldBe` [11, 12, 13]
it "concat" $
pmConcat [[1,2], [3], [4, 5]] `shouldBe` [1..5]
it "uniq" $
pmUniq [1,1,2,3,2] `shouldBe` [1,3,2]
it "intersect" $
pmIntersect [1,2,3,4] [2,4,5] `shouldBe` [2,4]
it "diff" $
pmDiff [1,2,3,4] [2,4,5] `shouldBe` [1,3]