For learning purpose, I've written a simple lambda calculus interpreter (plus 'Add'). I would like it to be the cleanest and most idiomatic possible.
Can we make it as neat as the Haskell version?
# lambda interpreter example.
# Values: Num, Fun & Wrong.
# Terms: Cons, Var, Lam, App & Add.
class Num:
def __init__(self, v):
self.v = v
def __str__(self):
return str(self.v)
class Fun:
def __init__(self, f):
self.f = f
def __call__(self, *args, **kargs):
return self.f(*args, **kargs)
def __str__(self):
return 'function'
class Wrong:
def __str__(self):
return 'Wrong'
def add(v1, v2):
return Num(v1.v + v2.v)
def apply(v1, v2):
return v1(v2)
class Cons:
def __init__(self, v):
self.v = int(v)
def interp(self, env):
return Num(self.v)
class Var:
def __init__(self, x):
self.x = x
def interp(self, env):
return env[self.x]
class Lam:
def __init__(self, arg, body):
self.arg = arg
self.body = body
def interp(self, env):
def f(v):
env2 = env.copy()
env2[self.arg] = v
return self.body.interp(env2)
return Fun(f)
class App:
def __init__(self, fun, param):
self.fun = fun
self.param = param
def interp(self, env):
return apply(self.fun.interp(env),
self.param.interp(env))
class Add:
def __init__(self, a, b):
self.a = a
self.b = b
def interp(self, env):
return add(self.a.interp(env), self.b.interp(env))
expr = App( Lam('x', Add(Var('x'), Var('x'))),
Add(Cons(10), Cons(11)) )
print(expr.interp({}))