[25] | 1 | {-# LANGUAGE TypeFamilies #-} |
---|
| 2 | |
---|
[19] | 3 | module Lambda where |
---|
| 4 | |
---|
| 5 | import qualified Data.Supply as S |
---|
| 6 | import qualified Data.Char as C |
---|
[25] | 7 | import Control.Monad.IO.Class (MonadIO, liftIO) |
---|
| 8 | import Data.IORef (newIORef, readIORef, writeIORef) |
---|
[19] | 9 | |
---|
| 10 | {- |
---|
| 11 | - Lambda calculus beagyazas |
---|
| 12 | -} |
---|
| 13 | class Lambda l where |
---|
[25] | 14 | lam :: (l a -> l b) -> l (a -> b) |
---|
| 15 | app :: l (a -> b) -> l a -> l b |
---|
[24] | 16 | lit :: Int -> l Int |
---|
[19] | 17 | |
---|
| 18 | {- |
---|
| 19 | - eval interpreter |
---|
| 20 | -} |
---|
| 21 | newtype Q a = Q { unQ :: a } |
---|
| 22 | instance Lambda Q where |
---|
[24] | 23 | lit = Q |
---|
[19] | 24 | lam a = Q (unQ.a.Q) |
---|
[20] | 25 | app a b = Q $ unQ a (unQ b) |
---|
[19] | 26 | |
---|
[20] | 27 | eval :: Q a -> a |
---|
[19] | 28 | eval = unQ |
---|
| 29 | |
---|
| 30 | {- |
---|
| 31 | - show interpreter |
---|
| 32 | -} |
---|
[20] | 33 | showVar :: Int -> String -> String |
---|
[19] | 34 | showVar x = if x>28 |
---|
| 35 | then showVar (x `div` 29) . showChar (C.chr $ C.ord 'a' + (x `mod` 29)) |
---|
| 36 | else showChar $ C.chr $ C.ord 'a' + x |
---|
| 37 | |
---|
[20] | 38 | -- unS :: Value supply -> Precedence -> ShowS |
---|
[19] | 39 | newtype S a = S { unS :: S.Supply Int -> Int -> ShowS } |
---|
[20] | 40 | |
---|
[19] | 41 | instance Lambda S where |
---|
[24] | 42 | lit a = S (\_ p -> showsPrec p a) |
---|
[19] | 43 | app (S fun) (S arg) = S (\s p -> |
---|
| 44 | let (s1, s2) = S.split2 s |
---|
| 45 | in showParen (p>6) $ fun s1 6 . showChar ' ' . arg s2 7) |
---|
| 46 | lam fun = S (\s p -> |
---|
| 47 | let (s1, s2) = S.split2 s |
---|
| 48 | v = S.supplyValue s1 |
---|
| 49 | showV = S $ \_ _ -> showVar v |
---|
| 50 | in showParen (p>0) $ showChar 'λ' . showVar v . showChar '.' . unS (fun showV) s2 0) |
---|
| 51 | |
---|
[20] | 52 | ast :: S a -> IO ShowS |
---|
[19] | 53 | ast a = do |
---|
| 54 | s <- S.newSupply 0 (+1) |
---|
| 55 | return $ unS a s 0 |
---|
| 56 | |
---|
[20] | 57 | printAst :: S a -> IO () |
---|
| 58 | printAst l = ast l >>= (\s -> putStrLn $ s "") |
---|
[25] | 59 | |
---|
| 60 | |
---|
| 61 | type family Sem (m :: * -> *) a :: * |
---|
| 62 | type instance Sem m Int = Int |
---|
| 63 | type instance Sem m (a -> b) = m (Sem m a) -> m (Sem m b) |
---|
| 64 | |
---|
| 65 | newtype R m a = R { unR :: m (Sem m a) } |
---|
| 66 | |
---|
| 67 | share :: (MonadIO m) => m a -> m (m a) |
---|
| 68 | share f = do |
---|
| 69 | mem <- liftIO $ newIORef (False, f) |
---|
| 70 | return $ do |
---|
| 71 | (evald, thunk) <- liftIO $ readIORef mem |
---|
| 72 | if evald then thunk |
---|
| 73 | else do |
---|
| 74 | value <- thunk |
---|
| 75 | liftIO $ writeIORef mem (True, return value) |
---|
| 76 | return value |
---|
| 77 | |
---|
| 78 | instance (MonadIO m) => Lambda (R m) where |
---|
| 79 | app x y = R $ unR x >>= ($ (unR y)) |
---|
| 80 | lit = R . return |
---|
| 81 | lam f = R . return $ (\x -> share x >>= unR . f . R) |
---|