aboutsummaryrefslogtreecommitdiff
path: root/sucl/basic.icl
diff options
context:
space:
mode:
Diffstat (limited to 'sucl/basic.icl')
-rw-r--r--sucl/basic.icl243
1 files changed, 243 insertions, 0 deletions
diff --git a/sucl/basic.icl b/sucl/basic.icl
new file mode 100644
index 0000000..f1ffb70
--- /dev/null
+++ b/sucl/basic.icl
@@ -0,0 +1,243 @@
+implementation module basic
+
+/*
+
+Basic definitions
+=================
+
+Description
+-----------
+
+Basic types and functions.
+
+*/
+
+import StdEnv
+
+/*
+
+Implementation
+--------------
+
+*/
+
+:: Optional t = Absent | Present t
+
+
+// Adjust a function for a single argument
+
+adjust :: !arg res (arg->res) !arg -> res | == arg
+adjust a r f x
+ | x==a = r
+ = f x
+
+
+// Claim a list of nodes from a heap
+claim :: ![.param] u:[.cell] -> ([.cell],v:[.cell]), [u<=v]
+
+claim [] heap = ([],heap)
+claim [pnode:pnodes] [snode:heap]
+= ([snode:snodes],heap`)
+ where (snodes,heap`) = claim pnodes heap
+claim pnodes emptyheap = abort "claim: out of heap" // Just in case. Should be used with an infinite heap.
+
+/* Depthfirst collects results of a function (called process), applied to a
+given list of inputs and other inputs which are generated from the
+results recursively, and so on. Duplicates are removed. */
+
+depthfirst :: (res->.[elem]) (elem->res) !.[elem] -> .[res] | == elem
+depthfirst generate process xs
+= snd (collect xs ([],[]))
+ where collect [] seenrest = seenrest
+ collect [x:xs] (seen,rest)
+ | isMember x seen
+ = collect xs (seen,rest)
+ = (seen``,[y:rest``])
+ where (seen`,rest``) = collect (generate y) ([x:seen],rest`)
+ (seen``,rest`) = collect xs ( seen`,rest)
+ y = process x
+
+// `Disjoint xs ys' checks whether xs and ys are disjoint.
+
+disjoint :: .[elem] !.[elem] -> Bool | == elem
+disjoint xs ys = not (or (map (flip isMember xs) ys))
+
+eqlen :: ![.elem1] ![.elem2] -> .Bool
+eqlen [x:xs] [y:ys] = eqlen xs ys
+eqlen [] [] = True
+eqlen xs ys = False
+
+// `Foldlm' is a combination of foldl and map.
+foldlm :: ((.collect,.elem) -> (.collect,.elem`)) !(.collect,![.elem]) -> (.collect,[.elem`])
+foldlm f (l,[]) = (l,[])
+foldlm f (l,[m:ms])
+= (l``,[m`:ms`])
+ where (l`,m`) = f (l,m)
+ (l``,ms`) = foldlm f (l`,ms)
+
+foldlr :: (.elem -> .((.lrinfo,.rlinfo) -> (.lrinfo,.rlinfo))) !(.lrinfo,.rlinfo) ![.elem] -> (.lrinfo,.rlinfo)
+foldlr f (l,r) []
+ = (l,r)
+foldlr f (l,r) [x:xs]
+ = (l``,r``)
+ where (l``,r`) = foldlr f (l`,r) xs
+ (l`,r``) = f x (l,r`)
+
+foldmap :: (x:res -> w:res`) w:res` -> u:(![(arg,x:res)] -> v:(arg -> w:res`)) | == arg, [v u <= w, v <= x]
+foldmap f d
+= foldr foldmap` (const d)
+ where foldmap` (x,y) g v = if (x==v) (f y) (g v)
+
+foldoptional :: .res .(.t -> .res) !(Optional .t) -> .res
+foldoptional absent present Absent = absent
+foldoptional absent present (Present x) = present x
+
+forget :: val -> .(![.(val,res)] -> .[(val,res)]) | == val
+forget x = filter (neq x o fst)
+neq x y = x <> y
+
+indent :: .String -> .([.String] -> .[String])
+indent first = map2 (+++) [first:repeat (createArray (size first) ' ')]
+
+map2 :: (.a -> .(.b -> .c)) ![.a] [.b] -> [.c]
+map2 f [x:xs] [y:ys] = [f x y:map2 f xs ys]
+map2 f _ _ = []
+
+// `Identifiers' is the list of all identifiers
+identifiers :: [String]
+identifiers =: map toString (tl (kleene ['abcdefghijklmnopqrstuvwxyz']))
+
+// `Intersect xs ys' is the intersection of list `ys' with list `xs'.
+intersect :: ![elem] [elem] -> .[elem] | == elem
+intersect [] _ = []
+intersect [y:ys] xs = elim (cons y o intersect ys) (intersect ys xs) y xs
+
+// Elim removes a given element from a list.
+// There are two continuations, one for failure and one for success.
+elim :: .(v:[elem] -> .res) .res elem u:[elem] -> .res | == elem, [u <= v]
+elim found notfound y []
+= notfound
+elim found notfound y [x:xs]
+| x==y
+= found xs
+= elim (found o cons x) notfound y xs
+
+// Cons prepends an element to a list
+cons :: .elem u:[.elem] -> v:[.elem], [u <= v]
+cons x xs = [x:xs]
+
+// `Join x xss' is the join of the list of lists `xss', separated by `x'.
+join :: a ![.[a]] -> .[a]
+join sep [] = []
+join sep [x:xs] = x++flatten (map (cons sep) xs)
+
+/* `Kleene xs' determines the kleene closure of the list `xs' of symbols,
+ i.e. all strings over that list in standard order. The implementation
+ is designed for maximum sharing.
+*/
+kleene :: !.[symbol] -> .[[symbol]]
+kleene [] = [[]]
+kleene symbols
+= flatten (iterate prefix [[]])
+ where prefix strings
+ = flatten (map appendstrings symbols)
+ where appendstrings symbol = map (cons symbol) strings
+
+lookup :: u:([(arg,w:res)] -> v:(arg -> w:res)) | == arg, [v u <= w]
+lookup = foldmap id (abort "lookup: not found")
+
+pairwith :: .(arg -> .res) arg -> (arg,.res)
+pairwith f x = (x,f x)
+
+plookup :: .(arg -> String) ![(arg,.res)] arg -> .res | == arg
+plookup showa tbl a = foldmap id (abort (showa a+++": not found")) tbl a
+
+power :: !Int (.t -> .t) -> .(.t -> .t)
+power n f
+| n <= 0
+= id
+= f o power (n-1) f
+
+printoptional :: .(.t -> String) !(Optional .t) -> String
+printoptional printa Absent = ""
+printoptional printa (Present a) = printa a
+
+proc :: .((w:elem -> .(.res -> .res)) -> v:(![w:elem] -> u:(.res -> .res))), [u <= v, u <= w]
+proc = flip o foldr
+
+mapfst :: v:(.a -> .b) -> u:((.a,.c) -> (.b,.c)), [u <= v]
+mapfst f = app2 (f,id)
+
+mapfst3 :: v:(.a -> .b) -> u:((.a,.c,.d) -> (.b,.c,.d)), [u <= v]
+mapfst3 f = app3 (f,id,id)
+
+maphd :: .(.a -> .a) !u:[.a] -> v:[.a], [u <= v]
+maphd f [] = []
+maphd f [x:xs] = [f x:xs]
+
+mapoptional :: .(.a -> .b) !(Optional .a) -> Optional .b
+mapoptional f Absent = Absent
+mapoptional f (Present x) = Present (f x)
+
+mappair :: .(.a -> .b) .(.c -> .d) !(.a,.c) -> (.b,.d)
+mappair f g (x,y) = (f x,g y)
+
+mapsnd :: v:(.a -> .b) -> u:((.c,.a) -> (.c,.b)), [u <= v]
+mapsnd f = app2 (id,f)
+
+maptl :: .(x:[.a] -> u:[.a]) !w:[.a] -> v:[.a], [u <= v, w <= x]
+maptl f [] = []
+maptl f [x:xs] = [x:f xs]
+
+maptriple :: x:(.a -> .b) w:(.c -> .d) v:(.e -> .f) -> u:((.a,.c,.e) -> (.b,.d,.f)), [u <= v, u <= w, u <= x]
+maptriple f g h = app3 (f,g,h)
+
+partition :: (a -> b) (a -> .c) -> .(!.[a] -> [(b,[.c])]) | == b
+partition f g
+= h
+ where h [] = []
+ h [x:xs]
+ = [((r,[g x:ins])):h outs]
+ where ins = [g x\\x<-xs|f x==r]
+ outs = [x\\x<-xs|f x<>r]
+ r = f x
+
+relimg :: ![(a,.b)] a -> [.b] | == a
+relimg rel x` = [y\\(x,y)<-rel|x==x`]
+
+remap :: a b [.(a,b)] -> .[(a,b)] | == a
+remap x y xys = [(x,y):forget x xys]
+
+shorter :: ![.a] [.b] -> .Bool
+shorter [] yys = False
+shorter [x:xs] [] = True
+shorter [x:xs] [y:ys] = shorter xs ys
+
+showbool :: .(!.Bool -> a) | fromBool a
+showbool = fromBool
+
+showoptional :: .(.a -> .String) !(Optional .a) -> String
+showoptional showa Absent = "Absent"
+showoptional showa (Present a) = "(Present "+++showa a+++")"
+
+showpair :: !.(.a -> .String) !.(.b -> .String) !(.a,.b) -> String
+showpair showa showb (a,b) = "("+++showa a+++","+++showb b+++")"
+
+showstring :: .(!.String -> a) | fromString a
+showstring = fromString
+
+showtriple :: !.(.a -> .String) !.(.b -> .String) !.(.c -> .String) !(.a,.b,.c) -> String
+showtriple showa showb showc (a,b,c) = "("+++showa a+++","+++showb b+++","+++showc c+++")"
+
+split :: a -> .(.[a] -> [.[a]]) | == a
+split sep
+= uncurry cons o spl
+ where spl [] = ([],[])
+ spl [x:xs]
+ | x==sep
+ = ([],[ys:yss])
+ = ([x:ys],yss)
+ where (ys,yss) = spl xs
+
+superset :: .[a] -> .(.[a] -> Bool) | == a
+superset set = isEmpty o (removeMembers set)