+module test
+
+import StdEnv
+import Data.Functor
+import Data.Func
+import Data.Maybe
+import Control.Applicative
+import Control.Monad
+
+:: In a b = In infixl 0 a b
+class lambda v
+where
+ (@) infixr 1 :: (v (a -> b)) (v a) -> v b
+ \| :: ((v a) -> v b) -> v (a -> b)
+
+class expr v
+where
+ lit :: a -> v a | toString a
+ (+.) infixl 6 :: (v a) (v a) -> v a | + a
+ (-.) infixl 6 :: (v a) (v a) -> v a | - a
+ (*.) infixl 6 :: (v a) (v a) -> v a | * a
+ (/.) infixl 6 :: (v a) (v a) -> v a | / a
+ (==.) infix 4 :: (v a) (v a) -> v Bool | == a
+ If :: (v Bool) (v a) (v a) -> v a
+
+class let v
+where
+ lett :: ((v a) -> In (v a) (v b)) -> v b
+
+:: Printer a = P ([String] [String] -> [String])
+unP (P a) = a
+print :: (Printer a) -> [String]
+print (P a) = a ["v" +++ toString i\\i<-[0..]] []
+instance lambda Printer
+where
+ (@) (P l) (P r) = P \i c->l i [" ":r i c]
+ \| def = P \[i:is] c->["(\\", i, "->":unP (def (P \_ c->[i:c])) is [")":c]]
+
+instance expr Printer
+where
+ lit a = P \i c->[toString a:c]
+ (+.) (P l) (P r) = P \i c->["(":l i ["+":r i [")":c]]]
+ (-.) (P l) (P r) = P \i c->["(":l i ["-":r i [")":c]]]
+ (*.) (P l) (P r) = P \i c->["(":l i ["*":r i [")":c]]]
+ (/.) (P l) (P r) = P \i c->["(":l i ["/":r i [")":c]]]
+ (==.) (P l) (P r) = P \i c->["(":l i ["==":r i [")":c]]]
+ If (P p) (P t) (P e) = P \i c->["if ":p i [" then ":t i [" else ":e i [" fi":c]]]]
+
+instance let Printer
+where
+ lett def = P \[i:is] c->
+ let (x In y) = def $ P \_ c->[i:c]
+ in ["let ",i,"=":(unP x) [i:is] [" in ":(unP y) is c]]
+
+eval :: (Maybe a) -> Maybe a
+eval a = a
+
+instance lambda Maybe
+where
+ (@) l r = ($) <$> l <*> r
+ \| def = Just (\a->fromJust (def (Just a)))
+
+instance expr Maybe
+where
+ lit a = pure a
+ (+.) l r = (+) <$> l <*> r
+ (-.) l r = (-) <$> l <*> r
+ (*.) l r = (*) <$> l <*> r
+ (/.) l r = (/) <$> l <*> r
+ (==.) l r = (==) <$> l <*> r
+ If i t e = if` <$> i <*> t <*> e
+
+instance let Maybe
+where
+ lett def = let (x In y) = def x in y
+
+Start = (print t, "\n", eval t)
+where
+ t :: (v Int) | expr, lambda, let v
+ t = lett \id =(\| \x->x)
+ In lett \fac=(\| \n->If (n ==. lit 0) (lit 1) (n *. (fac @ n -. lit 1)))
+ In fac @ lit 10