File: ExamplesFromManual.curry

package info (click to toggle)
curry-tools 1.0.1%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 5,492 kB
  • ctags: 121
  • sloc: makefile: 470; sh: 421
file content (119 lines) | stat: -rw-r--r-- 3,077 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import Test.Prop
import SearchTreeGenerators

rev :: [a] -> [a]
rev []     = []
rev (x:xs) = rev xs ++ [x]

-- Unit tests:
revNull = rev []      -=- []
rev123  = rev [1,2,3] -=- [3,2,1]

-- Property: reversing two times is the identity:
revRevIsId xs = rev (rev xs) -=- xs

-- Non-deterministic list insertion:
insert :: a -> [a] -> [a]
insert x xs     = x : xs
insert x (y:ys) = y : insert x ys

insertAsFirstOrLast :: Int -> [Int] -> Prop
insertAsFirstOrLast x xs = insert x xs ~> (x:xs ? xs++[x])

-- A permutation of a list:
perm :: [a] -> [a]
perm []     = []
perm (x:xs) = insert x (perm xs)

permLength :: [Int] -> Prop
permLength xs = length (perm xs) <~> length xs

permCount :: [Int] -> Prop
permCount xs = allDifferent xs ==> perm xs # fac (length xs)
 where
   fac n = foldr (*) 1 [1..n]

allDifferent []     = True
allDifferent (x:xs) = x `notElem` xs && allDifferent xs

-- Is a list sorted?
sorted :: [Int] -> Bool
sorted []       = True
sorted [_]      = True
sorted (x:y:zs) = x<=y && sorted (y:zs)

permIsEventuallySorted :: [Int] -> Prop
permIsEventuallySorted xs = eventually $ sorted (perm xs)

-- Permutation sort:
psort :: [Int] -> [Int]
psort xs | sorted ys = ys
 where ys = perm xs

psortIsAlwaysSorted xs = always $ sorted (psort xs)

psortKeepsLength xs = length (psort xs) <~> length xs

-- Quicksort:
qsort :: [Int] -> [Int] 
qsort []     = []
qsort (x:l)  = qsort (filter (<x) l) ++ x : qsort (filter (>=x) l)

qsortIsSorting xs = qsort xs <~> psort xs

--------------------------------------------------------------------------
-- Generating test data:

neg_or b1 b2 = not (b1 || b2) -=- not b1 && not b2


-- Natural numbers defined by s-terms (Z=zero, S=successor):
data Nat = Z | S Nat

-- addition on natural numbers:
add :: Nat -> Nat -> Nat
add Z     n = n
add (S m) n = S(add m n)

-- Property: the addition operator is commutative
addIsCommutative x y = add x y -=- add y x

-- Property: the addition operator is associative
addIsAssociative x y z = add (add x y) z -=- add x (add y z)


-- A general tree type:
data Tree a = Leaf a | Node [Tree a]

-- The leaves of a tree:
leaves (Leaf x) = [x]
leaves (Node ts) = concatMap leaves ts

-- Mirror a tree:
mirror (Leaf x) = Leaf x
mirror (Node ts) = Node (reverse (map mirror ts))

-- Property: double mirroring is the identity
doubleMirror t = mirror (mirror t) -=- t

-- Property: the leaves of a mirrored are in reverse order
leavesOfMirrorAreReversed t = leaves t -=- reverse (leaves (mirror t))

-- Sum up all numbers:
sumUp n = if n==0 then 0 else n + sumUp (n-1)

sumUpIsCorrect n = n>=0 ==> sumUp n -=- n * (n+1) `div` 2

-- To test sumUpIsCorrect explicitly on non-ngeative integers,
-- we define a new data type to wrap integers:
data NonNeg = NonNeg { nonNeg :: Int }

-- We define our own generator for producing only non-negative integers:
genNonNeg = genCons1 NonNeg genNN
 where
   genNN = genCons0 0 ||| genCons1 (\n -> 2*(n+1)) genNN
                      ||| genCons1 (\n -> 2*n+1)   genNN

-- Now we write our own test:
sumUpIsCorrectOnNonNeg = sumUpIsCorrect . nonNeg