IF to guardsThis is some general code on guarding things. I'm hoping to make it work out nicely.
First, the basics that must be expected of the expressions to be used in the guards.
<guard.sig>= [D->] signature GUARD_EXP = sig type exp val true' : exp val false' : exp val isTrue : exp -> bool val isFalse : exp -> bool val conjoin : exp * exp -> exp (* short-circuit, so order matters *) val negate : exp -> exp (* must be its own inverse *) end
Definesconjoin,exp,false',GUARD_EXP,isFalse,isTrue,negate,true'(links are to index).
Now, as many useful operations as I can think of.
<guard.sig>+= [<-D]
signature GUARD_LIKE = sig
structure Exp : GUARD_EXP
type 'a with_simple_guards = {guard : Exp.exp, value : 'a} list
type 'a with_guards (* = {guard : Exp.exp, value : 'a} list *)
val single : 'a -> 'a with_guards
val map : ('a -> 'b) -> 'a with_guards -> 'b with_guards
val dropFalse : 'a with_guards -> 'a with_guards
val guard : Exp.exp * 'a with_guards -> 'a with_guards
val metaGuard : Exp.exp with_guards * 'a with_guards -> 'a with_guards
val crossProduct : 'a with_guards list -> 'a list with_guards
(* these automatically drop false things *)
val crossPair : 'a with_guards * 'b with_guards -> ('a * 'b) with_guards
val flatten : 'a with_guards with_guards -> 'a with_guards
val ifMap : Exp.exp with_guards * 'a with_guards * 'a with_guards -> 'a with_guards
end
signature GUARD = sig
include GUARD_LIKE
sharing type with_guards = with_simple_guards
end
DefinescrossPair,crossProduct,dropFalse,Exp,flatten,GUARD,guard,GUARD_LIKE,ifMap,map,metaGuard,single,with_guards,with_simple_guards(links are to index).
<guard.sml>=
functor GuardFun(Exp : GUARD_EXP) : GUARD = struct
structure Exp = Exp
type 'a with_simple_guards = {guard : Exp.exp, value : 'a} list
type 'a with_guards = {guard : Exp.exp, value : 'a} list
<functions>
end
DefinesExp,GuardFun,with_guards,with_simple_guards(links are to index).
<functions>= (<-U) [D->]
fun single x = [{guard = Exp.true', value=x}]
fun map f l = List.map (fn {guard=g, value=x} => {guard=g, value=f x}) l
fun notFalse {guard=g, value} = not (Exp.isFalse g)
fun dropFalse l = List.filter notFalse l
fun guard (g, l) =
List.map (fn {guard=g', value=x} => {guard=Exp.conjoin(g, g'), value=x}) l
DefinesdropFalse,guard,map,notFalse,single(links are to index).
<functions>+= (<-U) [<-D->]
fun flatten l =
let fun flat ({guard=g, value=l}, tail) =
let fun crush ({guard=g', value=x}, tail) =
let val newGuard = Exp.conjoin(g, g')
in if Exp.isFalse newGuard then tail
else {guard=newGuard, value=x} :: tail
end
in foldr crush tail l
end
in foldr flat [] l
end
Definesflatten(links are to index).
<functions>+= (<-U) [<-D->]
fun cons ({guard=g, value=x}, {guard=g', value=tail}) =
{guard=Exp.conjoin(g, g'), value=x :: tail}
fun crossProduct l = foldr (Util'.crossProduct cons) (single []) l
Definescons,crossProduct(links are to index).
<functions>+= (<-U) [<-D->]
fun metaGuard (cond, value) =
let fun guard {guard=g1, value=g2} = Exp.conjoin(g1, g2)
fun guards' {guard=g1, value=g2} = Exp.conjoin(g1, Exp.negate g2)
fun --> (g, {guard=g', value=x}) = {guard=Exp.conjoin(g, g'), value=x}
in Util'.crossProduct --> (List.map guard cond, value)
end
DefinesmetaGuard(links are to index).
<functions>+= (<-U) [<-D->]
fun crossPair (x's, y's) =
let fun cons ({guard=g, value=x}, tail) =
let fun pair ({guard=g', value=y}, tail) =
let val g = Exp.conjoin(g, g')
in if Exp.isFalse g then tail else {guard=g, value=(x, y)} :: tail
end
in foldr pair tail y's
end
in foldr cons [] x's
end
DefinescrossPair(links are to index).
<functions>+= (<-U) [<-D]
fun ifMap (p, t, f) =
let val p' = map Exp.negate p
val t = metaGuard(p, t)
val f = metaGuard(p', f)
in dropFalse t @ dropFalse f
end
DefinesifMap(links are to index).