Functional logicο
Curry, Verse, Flix, Oz, β¦ all functional logic languages.
Values. A value v is either a variable x or a head-normal form hnf. A variable counts as a value because an expression may evaluate to an as-yet-unknown logical variable. A head-normal form hnf is a conventional value. Expressions e include values v and other constructs:
sequencing ππ; e. An βexpression or equationβ ππ is either an ordinary (possibly failing) expression e, or an equation v = e; the syntax ensures that equations can only occur to the left of a β; β.
βx. e - existential, introduces logical variable
fail - yield no values
choice e1 || e2 - yield multiple values (e1 followed by e2)
one{e} - if e fails, fails, otherwise returns the first of the values yielded by e
all{e} - reifies choices as a tuple; n choices mean tuple of length n
A program π ::= one{e} is a closed expression e (freevars(π) = β ) taking the first result. If the expression fails, the program fails.
Rewrite rules:
βx1 x2 Β·Β·Β· xn. e means βx1. βx2. Β·Β·Β·βxn. e
x := e1; e2 means βx. x = e1; e2
β¨e1, Β·Β·Β·, enβ© means x1 := e1; Β·Β·Β·; xn := en; β¨x1, Β·Β·Β·, xnβ© where xi are fresh (again skip rebinding values)
e1 = e2 meansβ‘ x := e1; x = e2; x where x is fresh (skip if e1 is a value v and the equation is not the last in a sequence)
if (βx1 Β·Β·Β·xn. e1) then e2 else e3 means (one{(βx1 Β·Β·Β·xn. e1; πβ¨β©. e2) || (πβ¨β©. e3)})β¨β©
Note: In the rules marked with a superscript πΌ, use πΌ-conversion to satisfy the side condition
A multi-equation pattern match such as:
function pat1 = body1
function pat2 = body2
desugars to
function = Ξ»p.((βx1 Β·Β·Β· xn. p = pat1; body1) || (βx1 Β·Β·Β· xn. p = pat2; body2))
Primops and literals:
Hnfs include integer constants and primitive operators +, >
e1 + e2 means addβ¨e1, e2β©
e1 > e2 means gtβ¨e1, e2β©
app-add addβ¨k1, k2β© ββ k3 where π3 = π1 + π2
app-gt gtβ¨k1, k2β© ββ k1 if π1 > π2
app-gt-fail gtβ¨k1, k2β© ββ fail if π1 β©½ π2
u-lit k1 = k2; e ββ e if π1 = π2
Lambdas:
A head-normal form hnf includes a lambda πx. e.
Expressions e include applications v1 v2
e1 e2 means f := e1; x := e2; f x, where f,x are fresh (skip rebinding values)
πβ¨x1, Β·Β·Β·, xnβ©. e means πp. βx1 Β·Β·Β· xn. p = β¨x1, Β·Β·Β·, xnβ©; e p fresh, n β©Ύ 0
app-betaπΌ (πx. e) (v) ββ e{v/x} if π₯ β fvs(v)
u-lambda a=b is stuck if a or b is a lambda
Tuples:
A head-normal form includes a tuple β¨v1, Β·Β·Β·, vnβ©.
app-tup β¨v0, Β·Β·Β·, vnβ©(v) ββ βx. x = v; (x = 0; v0) || Β·Β·Β· || (x = n; vn) fresh x β fvs(v, v0, Β·Β·Β·, vn)
app-tup-0 β¨β©(v) ββ fail
u-tup β¨v1, Β·Β·Β·, vnβ© = β¨vβ²1, Β·Β·Β·, vβ²nβ©; e ββ v1 = vβ²1; Β·Β·Β·; vn = vβ²n; e
all-choice all{v1 || Β·Β·Β· || vn } ββ β¨v1, Β·Β·Β·, vnβ©
all-value all{v} ββ β¨vβ©
all-fail all{fail} ββ β¨β©
Failure:
u-fail hnf1 = hnf2; e ββ fail if no unification
u-occurs x = V [ x ]; e ββ fail if V β β‘ (i.e., all but x=x fail)
fail-elim π [ fail] ββ fail
one-fail one{fail} ββ fail
choose-r fail || e ββ e
choose-l e || fail ββ e
Existential:
exi-elim βx. e ββ e if x β fvs(e)
eqn-elim βx. π [ x = v; e ] ββ π [ e ] if x β fvs(π [ e ]) and v β V [ x ]
exi-floatπΌ π [ βx. e ] ββ βx. π [ e ] if π₯ β fvs(π )
exi-swap βx. βy. e ββ βy. βx. e
Equality:
subst π [ x = v; e ] ββ (π {v/x}) [ x = v; e{v/x} ] if v β V [ x ]
hnf-swap hnf = v; e ββ v = hnf ; e
var-swap y = x; e ββ x = y; e if x βΊ y
Sequences:
seq-swap ππ; x = v; e ββ x = v; ππ; e unless (ππ is y = vβ² and y βͺ― x)
val-elim v; e ββ e
seq-assoc (ππ; e1); e2 ββ ππ; (e1; e2)
eqn-float v = (ππ; e1); e2 ββ ππ; (v = e1; e2)
Choice:
one-value one{v} ββ v
one-choice one{v || e} ββ v
choose-assoc (e1 || e2) || e3 ββ e1 || (e2 || e3)
choose SX [πΆπ [ e1 || e2 ] ] ββ SX [πΆπ [ e1 ] || πΆπ [ e2 ] ]