Python is not just an object-oriented imperative programming language, but also contains several features known from functional programming, such as higher-order functions, list comprehension, map/reduce/filter functions and lambda terms. However, more advanced concepts are not present in the language. Can they be emulated with existing Python facilities?
It turns out that this is indeed the case for some features.
- Infinite data structures
- embedding Haskell code
- others (upcoming…)
Infinite data structures are for example lists which are generated and can be traversed for many thousands of years without reaching the end. In Haskell, lazy evaluation makes this possible. Things are a bit less native in Python, but using generator-style sequence objects, infinite lists can be brought to the programmer:
# Generator ‘Y’ around Fibonacci function
seq = Y(fib)
# Let’s print some slice of this list
seqslice = seq[5:20]
print seqslice
# Eternal iteration…
for y in seqslice:
print y
Y is in this case the generator sequence object. Note that lazy evaluation is one of the features which probably cannot be done in Python without modifying the interpreter, so the zip() function will return a Memory Error.
But, we’re cool, eh?
# Our own zip which handles infinite structures
def xzip(l1, l2):
return lambda x: (l1(x), l2(x))
# Make a companion function to fib()
def id(n):
return n
# Use it like this
for t in Y(xzip(id, fib)):
print t
Now let’s make things even more cool: How about freely mixing Python and Haskell code?
Getting the best out of both worlds is the goal of the haskellembed module. A quick functionality overview:
#!/usr/bin/env python
# Import the haskellembed module
import haskellembed
# Define some code (could also be in external *.hs file)
code = “"”
– konstanter Wert
fs :: Int
fs = 4
– Addition um konstanten Wert
fs2 :: Int -> Int
fs2 n = n + 1
– Rekursive Berechnung der Fibonacci-Funktion
fs3 :: Int -> Int
fs3 1 = 1
fs3 2 = 1
fs3 n = fs3 (n - 2) + fs3 (n - 1)
– Wildcards
fs4 :: Int -> Int -> Int
fs4 n _ = n * 3
– Guards
fs5 :: Int -> Int
fs5 n | n > 0 = 42
| otherwise = -10
– Lambda-Notation
fs6 = x y -> x + y
“"”
# Now, convert Haskell to Python on the fly
# and inject the public functions into our namespace
# Alternatively, without giving globals(), a sandbox is created in h which lets you access internals as well and inject as needed
h = haskellembed.convert(code, globals())
# Finally, just use the Haskell functions!
print fs6(10, 20)
The cool thing is that using Python functions from within the Haskell code now becomes natural. Just use time.time() in an expression and voilà, as long as Hugs or other interpreters accept the code, Python will execute it just fine.
Of course, the conversion support is limited to the above examples for the time being. But interesting times are ahead, adding more features can be done within minutes.