summaryrefslogtreecommitdiff
path: root/assignment-1/program1.icl
blob: 611894fc22150dad0fae43b84a1ca929e39c1e18 (plain) (blame)
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
120
121
122
123
124
125
126
module program1

import StdBool
import StdEnum
from StdFunc import flip, o
import StdList
import StdString
import StdTuple

import Control.Applicative
import Control.Monad
import Control.Monad.State
import Data.Functor
import Data.List
import Data.Maybe

:: Bin a = Leaf | Bin (Bin a) a (Bin a)
:: Rose a = Rose a [Rose a]

instance == (Bin a) | == a
where
	== Leaf Leaf = True
	== (Bin la xa ra) (Bin lb xb rb) = xa == xb && la == lb && ra == rb
	== _ _ = False

instance == (Rose a) | == a
where
	== (Rose x xs) (Rose y ys) = x == y && xs == ys

class serialize a
where
	write :: a [String] -> [String]
	read :: [String] -> Maybe (a, [String])

sread :== StateT read

instance serialize Bool
where
	write b c = [toString b:c]
	read ["True": r] = Just (True,  r)
	read ["False":r] = Just (False, r)
	read _           = Nothing

instance serialize String
where
	write s c = [s:c]
	read [s:r] = Just (s,r)
	read _     = Nothing

instance serialize Int
where
	write i c = write (toString i) c
	read ["0":r] = Just (0, r)
	read [i:r] = case toInt i of
		0 -> Nothing
		i -> Just (i, r)
	read _ = Nothing

instance serialize [a] | serialize a
where
	// We don't actually need to start with [, but this gives some type safety.
	// The ] is necessary to recognise the end of the list.
	write xs c = write "[" (foldl (flip write) (write "]" c) xs)
	read ["[":r] = readElements [] r
	where
		readElements :: [a] [String] -> Maybe ([a], [String]) | serialize a
		readElements xs ["]":r] = Just (xs, r)
		readElements xs s = read s >>= \(x,r) -> readElements [x:xs] r
	read _ = Nothing

instance serialize (Bin a) | serialize a
where
	// Here, it is necessary to start with "Bin", to be able to parse
	// ["Leaf":_] unambiguously.
	write Leaf c = write "Leaf" c
	write (Bin l x r) c = write "Bin" (write l (write x (write r c)))
	read ["Leaf":r] = Just (Leaf, r)
	read ["Bin":r] = runStateT (liftM3 Bin sread sread sread) r
	read _ = Nothing

instance serialize (Rose a) | serialize a
where
	// Other than for [], we don't include the constructor here (it is not
	// necessary because there is only one constructor).
	write (Rose x xs) c = write xs (write x c)
	read s = runStateT (liftM2 (flip Rose) sread sread) s

test :: a -> (Bool, [String]) | serialize, == a
test a = (isJust r && fst jr == a && isEmpty (tl (snd jr)), s)
where
	s = write a [""]
	r = read s
	jr = fromJust r

Start :: [([Rose (Bin Bool)], Bool)] // Change the first type of the tuple to test other expressions.
Start = filter (not o snd) testn // Should be [].

testn :: [(a, Bool)] | serialize, ==, someExprs a
testn = [(x, fst (test x)) \\ x <- someExprs]

class someExprs a :: [a]

instance someExprs Bool where someExprs = [True,False]
instance someExprs Int where someExprs = [-3..3]
instance someExprs [a] | someExprs a where someExprs = tails someExprs
instance someExprs (Bin a) | someExprs a
where
	someExprs =
		[ Leaf
		, Bin Leaf (es!!0) Leaf
		, Bin (Bin (Bin (Bin Leaf (es!!1) Leaf) (es!!2) Leaf) (es!!3) Leaf) (es!!4) Leaf
		, Bin (Bin Leaf (es!!7) Leaf) (es!!6) (Bin Leaf (es!!5) Leaf)
		, Bin Leaf (es!!8) (Bin (Bin (Bin Leaf (es!!9) Leaf) (es!!10) Leaf) (es!!11) Leaf)
		] // Looking forward to using Gast.
	where
		es = cycle someExprs
instance someExprs (Rose a) | someExprs a
where
	someExprs = level1 ++ level2 ++ level3
	where
		level1 = [Rose x [] \\ x <- someExprs]
		level2 = [Rose x rs \\ x <- someExprs, rs <- tails level1]
		level3 = [Rose x rs \\ x <- someExprs, rs <- tails (level1 ++ level2)]
		// Would be better to use (a) permutations / subsequences or (b) do
		// something more intelligent, but (a) takes too much memory and (b)
		// requires thinking.