forked from logpy/logpy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharith.py
82 lines (57 loc) · 1.66 KB
/
arith.py
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
import operator
from unification import isvar
from .core import (eq, EarlyGoalError, lany)
def gt(x, y):
""" x > y """
if not isvar(x) and not isvar(y):
return eq(x > y, True)
else:
raise EarlyGoalError()
def lt(x, y):
""" x > y """
if not isvar(x) and not isvar(y):
return eq(x < y, True)
else:
raise EarlyGoalError()
def lor(*goalconsts):
""" Logical or for goal constructors
>>> from kanren.arith import lor, eq, gt
>>> gte = lor(eq, gt) # greater than or equal to is `eq or gt`
"""
def goal(*args):
return lany(*[gc(*args) for gc in goalconsts])
return goal
gte = lor(gt, eq)
lte = lor(lt, eq)
def binop(op, revop=None):
""" Transform binary operator into goal
>>> from kanren.arith import binop
>>> import operator
>>> add = binop(operator.add, operator.sub)
>>> from kanren import var, run
>>> x = var('x')
>>> next(add(1, 2, x)({}))
{~x: 3}
"""
def goal(x, y, z):
if not isvar(x) and not isvar(y):
return eq(op(x, y), z)
if not isvar(y) and not isvar(z) and revop:
return eq(x, revop(z, y))
if not isvar(x) and not isvar(z) and revop:
return eq(y, revop(z, x))
raise EarlyGoalError()
goal.__name__ = op.__name__
return goal
add = binop(operator.add, operator.sub)
add.__doc__ = """ x + y == z """
mul = binop(operator.mul, operator.truediv)
mul.__doc__ = """ x * y == z """
mod = binop(operator.mod)
mod.__doc__ = """ x % y == z """
def sub(x, y, z):
""" x - y == z """
return add(y, z, x)
def div(x, y, z):
""" x / y == z """
return mul(z, y, x)