Source code for tootle

import inspect

import types

import functools
import turtle


import enum
import pint
ureg = pint.UnitRegistry()


# Side Note: Yes, Python has enums !
[docs]class PenState(enum.Enum): UP = -1 DOWN = 1
# The usual OO delegation interface # taking turtle.Turtle as an unknown black box. # Composition, not inheritance. # The state is also used here as the interface to the python turtle implementation. class TurtleState: @property def position(self) -> int: return self.real.position() @property def angle(self) -> int: return self.real.heading() @property def penState(self) -> PenState: return self.real.pen().get('pendown') def __init__(self): self.real = turtle.Tootle() def move(self, distance: int): self.real.forward(distance=distance) def right(self, angle: int): self.real.right(angle) def left(self, angle: int): self.real.left(angle) def penup(self): self.real.penup() def pendown(self): self.real.pendown() # metaclass as type class # https://en.wikibooks.org/wiki/Haskell/The_Functor_class class Functor: # https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/ @classmethod def __prepare__(mcs, name, bases): pass def __call__(self, *args, **kwargs): pass #: fmap :: (a -> b) -> f a -> f b def fmap(self, pure): raise NotImplementedError def test_id(self): pass def test_composition(self): pass class Applicative(Functor): #: pure :: a -> f a def pure(self): pass #: (<*>) :: f (a -> b) -> f a -> f b def apply(self): pass # pure id <*> v = v -- Identity def test_identity(self): pass # pure f <*> pure x = pure (f x) -- Homomorphism def test_homomorphism(self): pass # u <*> pure y = pure ($ y) <*> u -- Interchange def test_interchange(self): pass # pure (.) <*> u <*> v <*> w = u <*> (v <*> w) -- Composition def test_composition(self): pass # fmap f x = pure f <*> x -- fmap def test_fmap(self): pass class Monad: def constructor(self): pass #: return :: a -> m a def _return(self): return lambda x: x #: (>>=) :: m a -> (a -> m b) -> m b def _bind(self): pass #: m >>= return = m -- right unit def test_unit_right(self): pass #: return x >>= f = f x -- left unit def test_unit_left(self): pass #: (m >>= f) >>= g = m >>= (\x -> f x >>= g) -- associativity def test_associativity(self): pass class State: # (functools) ? def __init__(self, distance): # TODO assert type early to avoid headache while debugging. self.partial = functools.partial(TurtleState.move, distance=distance) def __call__(self, *args, **kwargs): self.value, val = self.partial(*args, **kwargs) return val def __enter__(self): # We do not want to apply here. # Instead we prepare for introspection... # TODO return self.partial def __exit__(self, exc_type, exc_val, exc_tb): pass def compose(f, g): f(g) class MonadicTurtle: # Constructor def __init__(self): # TODO : make this parameterizable somehow self.tstate = TurtleState() def __call__(self, *args, **kwargs): pass def __enter__(self): return self def move(self, distance: int): # TMP HACK distance = int(distance) return functools.partial(TurtleState.move, distance=distance) def right(self, angle: int): # TMP HACK angle = int(angle * ureg.degrees) def stateFun(state: TurtleState): state.right(angle) return state return State(stateFun) def left(self, angle: int): # TMP HACK angle = int(angle) def stateFun(state: TurtleState): state.left(angle) return state return State(stateFun) def penup(self): def stateFun(state: TurtleState): state.penup() return state return State(stateFun) def pendown(self): def stateFun(state: TurtleState): state.pendown() return state return State(stateFun) def __exit__(self, exc_type, exc_val, exc_tb): pass