Source code for metadsl_core.function

"""
This module is built on top of the abstraction

It adds the ability to have multiple arities and names attached to functions.

Because MyPy doesn't support multiple arity generics, we need a seperate class for each arity of
function.
"""
from __future__ import annotations


from metadsl import *
from metadsl_rewrite import *

from .strategies import *
from .abstraction import *
from .conversion import *
from .maybe import *
import typing

__all__ = ["FunctionZero", "FunctionOne", "FunctionTwo", "FunctionThree"]


T = typing.TypeVar("T")
U = typing.TypeVar("U")
V = typing.TypeVar("V")
X = typing.TypeVar("X")


[docs]class FunctionZero(Expression, typing.Generic[T]): """ Function with zero args. """
[docs] @expression @classmethod def from_fn(cls, fn: typing.Callable[[], T]) -> FunctionZero[T]: return cls.create(fn.__name__, fn())
@expression def __call__(self) -> T: ...
[docs] @expression @classmethod def create(cls, name: str, val: T) -> FunctionZero[T]: ...
@property # type: ignore @expression def value(self) -> T: ...
[docs] @expression # type: ignore @property def name(self) -> str: ...
[docs]class FunctionOne(Expression, typing.Generic[T, U]): """ Function with one arg. """
[docs] @expression @classmethod def from_fn( cls, fn: typing.Callable[[T], U], name=Maybe[str].nothing() ) -> FunctionOne[T, U]: return cls.create(name.default(fn.__name__), Abstraction.from_fn(fn))
[docs] @expression @classmethod def from_fn_recursive( cls, fn: typing.Callable[[FunctionOne[T, U], T], U] ) -> FunctionOne[T, U]: @Abstraction.fix @Abstraction.from_fn def inner(inner_abst: Abstraction[T, U]) -> Abstraction[T, U]: inner_fn = cls.create(fn.__name__, inner_abst) @Abstraction.from_fn def inner(arg1: T) -> U: return fn(inner_fn, arg1) return inner return cls.create(fn.__name__, inner)
@expression def __call__(self, arg: T) -> U: ...
[docs] @expression @classmethod def create(cls, name: str, val: Abstraction[T, U]) -> FunctionOne[T, U]: ...
[docs] @expression # type: ignore @property def abstraction(self) -> Abstraction[T, U]: ...
[docs] @expression # type: ignore @property def name(self) -> str: ...
[docs] @expression # type: ignore @property def unfix(self) -> Abstraction[FunctionOne[T, U], FunctionOne[T, U]]: ...
[docs]class FunctionTwo(Expression, typing.Generic[T, U, V]): """ Function with two args. """
[docs] @expression @classmethod def from_fn(cls, fn: typing.Callable[[T, U], V]) -> FunctionTwo[T, U, V]: def inner(arg1: T) -> Abstraction[U, V]: def inner(arg2: U) -> V: return fn(arg1, arg2) return Abstraction.from_fn(inner) return cls.create(fn.__name__, Abstraction.from_fn(inner))
[docs] @expression @classmethod def from_fn_recursive( cls, fn: typing.Callable[[FunctionTwo[T, U, V], T, U], V] ) -> FunctionTwo[T, U, V]: @Abstraction.fix @Abstraction.from_fn def inner( inner_abst: Abstraction[T, Abstraction[U, V]] ) -> Abstraction[T, Abstraction[U, V]]: inner_fn = cls.create(fn.__name__, inner_abst) @Abstraction.from_fn def inner(arg1: T) -> Abstraction[U, V]: @Abstraction.from_fn def inner(arg2: U) -> V: return fn(inner_fn, arg1, arg2) return inner return inner return cls.create(fn.__name__, inner)
@expression def __call__(self, arg1: T, arg2: U) -> V: ...
[docs] @expression @classmethod def create( cls, name: str, val: Abstraction[T, Abstraction[U, V]] ) -> FunctionTwo[T, U, V]: ...
[docs] @expression # type: ignore @property def abstraction(self) -> Abstraction[T, Abstraction[U, V]]: ...
[docs] @expression # type: ignore @property def name(self) -> str: ...
[docs] @expression # type: ignore @property def unfix(self) -> Abstraction[FunctionTwo[T, U, V], FunctionTwo[T, U, V]]: ...
[docs]class FunctionThree(Expression, typing.Generic[T, U, V, X]): """ Function with three args. """
[docs] @expression @classmethod def from_fn(cls, fn: typing.Callable[[T, U, V], X]) -> FunctionThree[T, U, V, X]: @Abstraction.from_fn def inner(arg1: T) -> Abstraction[U, Abstraction[V, X]]: @Abstraction.from_fn def inner(arg2: U) -> Abstraction[V, X]: @Abstraction.from_fn def inner(arg3: V) -> X: return fn(arg1, arg2, arg3) return inner return inner return cls.create(fn.__name__, inner)
[docs] @expression @classmethod def from_fn_recursive( cls, fn: typing.Callable[[FunctionThree[T, U, V, X], T, U, V], X] ) -> FunctionThree[T, U, V, X]: @Abstraction.fix @Abstraction.from_fn def inner( inner_abst: Abstraction[T, Abstraction[U, Abstraction[V, X]]] ) -> Abstraction[T, Abstraction[U, Abstraction[V, X]]]: inner_fn = cls.create(fn.__name__, inner_abst) @Abstraction.from_fn def inner(arg1: T) -> Abstraction[U, Abstraction[V, X]]: @Abstraction.from_fn def inner(arg2: U) -> Abstraction[V, X]: @Abstraction.from_fn def inner(arg3: V) -> X: return fn(inner_fn, arg1, arg2, arg3) return inner return inner return inner return cls.create(fn.__name__, inner)
@expression def __call__(self, arg1: T, arg2: U, arg3: V) -> X: ...
[docs] @expression @classmethod def create( cls, name: str, val: Abstraction[T, Abstraction[U, Abstraction[V, X]]] ) -> FunctionThree[T, U, V, X]: ...
[docs] @expression # type: ignore @property def abstraction(self) -> Abstraction[T, Abstraction[U, Abstraction[V, X]]]: ...
[docs] @expression # type: ignore @property def name(self) -> str: ...
[docs] @expression # type: ignore @property def unfix( self, ) -> Abstraction[FunctionThree[T, U, V, X], FunctionThree[T, U, V, X]]: ...
register.pre(default_rule(FunctionZero[T].from_fn)) register.pre(default_rule(FunctionOne[T, U].from_fn)) register.pre(default_rule(FunctionTwo[T, U, V].from_fn)) register.pre(default_rule(FunctionThree[T, U, V, X].from_fn)) register.pre(default_rule(FunctionOne[T, U].from_fn_recursive)) register.pre(default_rule(FunctionTwo[T, U, V].from_fn_recursive)) register.pre(default_rule(FunctionThree[T, U, V, X].from_fn_recursive)) @register_ds # type: ignore @rule def zero_call(_: str, v: T) -> R[T]: return FunctionZero.create(_, v)(), v @register_ds # type: ignore @rule def one_call(_: str, a: Abstraction[T, U], t: T) -> R[U]: return FunctionOne.create(_, a)(t), a(t) @register_ds # type: ignore @rule def two_call(_: str, a: Abstraction[T, Abstraction[U, V]], t: T, u: U) -> R[V]: return FunctionTwo.create(_, a)(t, u), a(t)(u) @register_ds # type: ignore @rule def three_call( _: str, a: Abstraction[T, Abstraction[U, Abstraction[V, X]]], t: T, u: U, v: V ) -> R[X]: return FunctionThree.create(_, a)(t, u, v), a(t)(u)(v) @register_core # type: ignore @rule def zero_value(_: str, t: T) -> R[T]: return FunctionZero.create(_, t).value, t @register_core # type: ignore @rule def one_abstraction(fn: FunctionOne[T, U]) -> R[Abstraction[T, U]]: return fn.abstraction, lambda: Abstraction[T, U].from_fn(lambda t: fn(t)) @register_core # type: ignore @rule def two_abstraction(fn: FunctionTwo[T, U, V]) -> R[Abstraction[T, Abstraction[U, V]]]: return ( fn.abstraction, lambda: Abstraction[T, Abstraction[U, V]].from_fn( lambda t: Abstraction[U, V].from_fn(lambda u: fn(t, u)) ), ) @register_core # type: ignore @rule def three_abstraction( fn: FunctionThree[T, U, V, X] ) -> R[Abstraction[T, Abstraction[U, Abstraction[V, X]]]]: return ( fn.abstraction, lambda: Abstraction[T, Abstraction[U, Abstraction[V, X]]].from_fn( lambda t: Abstraction[U, Abstraction[V, X]].from_fn( lambda u: Abstraction[V, X].from_fn(lambda v: fn(t, u, v)) ) ), ) @register_core # type: ignore @rule def zero_name(name: str, t: T): return FunctionZero.create(name, t).name, name @register_core # type: ignore @rule def one_name(_: str, abst: Abstraction[T, U]): return FunctionOne.create(_, abst).name, _ @register_core # type: ignore @rule def two_name(_: str, abst: Abstraction[T, Abstraction[U, V]]): return FunctionTwo.create(_, abst).name, _ @register_core # type: ignore @rule def three_name(_: str, abst: Abstraction[T, Abstraction[U, Abstraction[V, X]]]): return FunctionThree.create(_, abst).name, _ @register.pre # type: ignore @rule def one_unfix(name: str, abst: Abstraction[T, U]): def result(): @Abstraction.from_fn def inner(fn: FunctionOne[T, U]) -> FunctionOne[T, U]: return FunctionOne.create(name, abst.unfix(fn.abstraction)) return inner return FunctionOne.create(name, abst).unfix, result @register.pre # type: ignore @rule def two_unfix(name: str, abst: Abstraction[T, Abstraction[U, V]]): def result(): @Abstraction.from_fn def inner(fn: FunctionTwo[T, U, V]) -> FunctionTwo[T, U, V]: return FunctionTwo.create(name, abst.unfix(fn.abstraction)) return inner return FunctionTwo.create(name, abst).unfix, result @register.pre # type: ignore @rule def three_unfix(name: str, abst: Abstraction[T, Abstraction[U, Abstraction[V, X]]]): def result(): @Abstraction.from_fn def inner(fn: FunctionThree[T, U, V, X]) -> FunctionThree[T, U, V, X]: return FunctionThree.create(name, abst.unfix(fn.abstraction)) return inner return FunctionThree.create(name, abst).unfix, result @register_convert @rule def function_zero_convert( name: str, callable_zero: typing.Callable[[], T], value: T, # callable_one: typing.Callable[[T], U], # abs_one: Abstraction[T, U], ) -> R[Maybe[FunctionZero[Maybe[U]]]]: # From callable -> function yield ( Converter[FunctionZero[Maybe[U]]].convert(callable_zero), lambda: Converter[FunctionZero[Maybe[U]]].convert( FunctionZero.from_fn(callable_zero) ), ) # from function -> value yield ( Converter[FunctionZero[Maybe[U]]].convert(FunctionZero.create(name, value)), Maybe.just(FunctionZero.create(name, Converter[U].convert(value))), ) @register_convert @rule def function_one_convert( name: str, callable_one: typing.Callable[[T], U], abs_one: Abstraction[T, U], ) -> R[Maybe[FunctionOne[V, Maybe[X]]]]: yield ( Converter[FunctionOne[V, Maybe[X]]].convert(callable_one), lambda: Converter[FunctionOne[V, Maybe[X]]].convert( FunctionOne.from_fn(callable_one) ), ) yield ( Converter[FunctionOne[V, Maybe[X]]].convert(FunctionOne.create(name, abs_one)), lambda: Converter[Abstraction[V, Maybe[X]]] .convert(abs_one) .map( Abstraction[Abstraction[V, Maybe[X]], FunctionOne[V, Maybe[X]]].from_fn( lambda converted_abs: FunctionOne.create(name, converted_abs) ) ), ) @register_convert @rule def convert_fn_to_abstraction( a: typing.Callable[[T], U] ) -> R[Maybe[Abstraction[V, Maybe[X]]]]: return ( Converter[Abstraction[V, Maybe[X]]].convert(a), lambda: Converter[Abstraction[V, Maybe[X]]].convert(Abstraction.from_fn(a)), )