[27] | 1 | {-# LANGUAGE TypeFamilies, GADTs, Rank2Types, TemplateHaskell #-} |
---|
[25] | 2 | |
---|
[19] | 3 | module Lambda where |
---|
| 4 | |
---|
| 5 | import qualified Data.Supply as S |
---|
| 6 | import qualified Data.Char as C |
---|
[27] | 7 | import Data.Lens.Light |
---|
[19] | 8 | |
---|
| 9 | {- |
---|
| 10 | - Lambda calculus beagyazas |
---|
| 11 | -} |
---|
| 12 | class Lambda l where |
---|
[25] | 13 | lam :: (l a -> l b) -> l (a -> b) |
---|
| 14 | app :: l (a -> b) -> l a -> l b |
---|
[24] | 15 | lit :: Int -> l Int |
---|
[19] | 16 | |
---|
| 17 | {- |
---|
| 18 | - eval interpreter |
---|
| 19 | -} |
---|
| 20 | newtype Q a = Q { unQ :: a } |
---|
| 21 | instance Lambda Q where |
---|
[24] | 22 | lit = Q |
---|
[19] | 23 | lam a = Q (unQ.a.Q) |
---|
[20] | 24 | app a b = Q $ unQ a (unQ b) |
---|
[19] | 25 | |
---|
[20] | 26 | eval :: Q a -> a |
---|
[19] | 27 | eval = unQ |
---|
| 28 | |
---|
| 29 | {- |
---|
[27] | 30 | - show interpreter |
---|
| 31 | -} |
---|
[20] | 32 | showVar :: Int -> String -> String |
---|
[19] | 33 | showVar x = if x>28 |
---|
| 34 | then showVar (x `div` 29) . showChar (C.chr $ C.ord 'a' + (x `mod` 29)) |
---|
| 35 | else showChar $ C.chr $ C.ord 'a' + x |
---|
| 36 | |
---|
[27] | 37 | class SContext a where |
---|
| 38 | supply :: Lens a (S.Supply Int) |
---|
| 39 | prec :: Lens a Int |
---|
[20] | 40 | |
---|
[27] | 41 | newtype S ctx a = S { unS :: ctx -> ShowS } |
---|
| 42 | |
---|
| 43 | instance SContext ctx => Lambda (S ctx) where |
---|
| 44 | lit a = S (\ctx -> showsPrec (getL prec ctx) a) |
---|
| 45 | app (S fun) (S arg) = S (\ctx -> |
---|
| 46 | let (s1, s2) = S.split2 (getL supply ctx) |
---|
| 47 | p = getL prec ctx |
---|
| 48 | in showParen (p>6) $ fun (updateCtx s1 6 ctx) . showChar ' ' . arg (updateCtx s2 7 ctx)) |
---|
| 49 | lam fun = S (\ctx -> |
---|
| 50 | let (s1, s2) = S.split2 (getL supply ctx) |
---|
[19] | 51 | v = S.supplyValue s1 |
---|
[27] | 52 | p = getL prec ctx |
---|
| 53 | showV = S $ \ctx -> showVar v |
---|
| 54 | in showParen (p>0) $ showChar 'λ' . showVar v . showChar '.' . unS (fun showV) (updateCtx s2 0 ctx)) |
---|
[19] | 55 | |
---|
[27] | 56 | updateCtx :: SContext ctx => S.Supply Int -> Int -> ctx -> ctx |
---|
| 57 | updateCtx s p = setL supply s . setL prec p |
---|
| 58 | |
---|
| 59 | data SData = SData { _getSDataSupply :: S.Supply Int, _getSDataPrec :: Int } |
---|
| 60 | $(makeLens ''SData) |
---|
| 61 | |
---|
| 62 | instance SContext SData where |
---|
| 63 | supply = getSDataSupply |
---|
| 64 | prec = getSDataPrec |
---|
| 65 | |
---|
| 66 | ast :: S SData a -> IO ShowS |
---|
[19] | 67 | ast a = do |
---|
| 68 | s <- S.newSupply 0 (+1) |
---|
[27] | 69 | return $ unS a $ SData s 0 |
---|
[19] | 70 | |
---|
[27] | 71 | printAst :: S SData a -> IO () |
---|
[20] | 72 | printAst l = ast l >>= (\s -> putStrLn $ s "") |
---|
[25] | 73 | |
---|