Pykell
Python functional programming library inspired by Haskell.
This is a personal project to deepen my understanding of functional programming by implementing this DSL in python.
It is open-source, so feel free to open issues and pull requests!
Installing
We have a stable release under pypi:
pip install pykell
Features
This DSL makes it easy to write functional programming patters with a clean syntax.
Functions
This is an abstraction layer on top of Python regular functions and lambdas.
from pykell.typing import Function
from pykell.functions import F
@F
def f(x: int, y: float) -> float: return x + y
g = F[float, str](lambda x: f"This is a float: {x}")
f
f2 = f |2
f2_ = f(2)
my_float = f2 |1.5
h = f2 >> g
h | 1.2
x = f |2 |1.5
Containers
These are well known containers that can make your life easyer when programming.
from pykell.typing import Maybe, Just, Nothing, Error, Result
def f(x: int) -> Maybe[int]:
return Just(x + 10) if x < 10 else Nothing()
def f(x: int) -> Result[int, Exception]:
return Just(x + 10) if x < 10 else Error(Exception("This is too big!!!"))
Functors
This is some syntatic sugar to use functors in python.
from pykell.typing import Function
from pykell.functors import Functor
@Functor
def int_to_str(f: Function[int, float]) -> Function[str, str]:
return lambda x: str(f(int(x)))
f = F[int, float](lambda x: x / 7)
g = F[int, float](lambda x: x * 8)
new_f: Function[str, str] = int_to_str(f)
with int_to_str:
x = f |"1"
y = f |"3"
z = f(7)
Containers
These are well known containers that can make your life easyer when programming.
from pykell.typing import Maybe, Just, Nothing, Error, Result
def f(x: int) -> Maybe[int]:
return Just(x + 10) if x < 10 else Nothing()
def f(x: int) -> Result[int, Exception]:
return Just(x + 10) if x < 10 else Error(Exception("This is too big!!!"))
Arrays
This is inspired by other array language features but use haskells lazyness to do computations.
from pykell.arrays import arr
result = (
arr([1, 2, 3])
.map(lambda x: x + 1)
.filter(lambda x: x % 2 != 0)
.fold(0, lambda acc, cur: cur + acc)
)
print(result._)
def naturals():
i = 0
while True:
yield (i := i + 1)
result = (
arr(naturals())
.map(lambda x: x + 1)
.filter(lambda x: x % 2 != 0)
.take(10)
)
print(result._)
Monads
This is a good one.
from pykell.monads import MaybeMonad
from pykell.functions import F
from pykell.typing import Maybe, Just, Nothing
f = F[int, Maybe[int]](lambda x: Just(x + 10) if x < 10 else Nothing())
g = F[int, Maybe[float]](lambda x: Just(x / 7) if x < 10 else Nothing())
@MaybeMonad.do
def calculate(x):
y: int = yield f(x)
if y < 5:
return y + 5
z: float = yield g(z)
return z - 1.5
calculate(-10)
calculate(4)
calculate(11)
Contributions
This is just an experiment. If you have any ideas of features you want to see in here please reach out!