source: sizechecking/branches/macs/Lambda.hs @ 25

Last change on this file since 25 was 25, checked in by gobi, 11 years ago

monad for observable sharing

File size: 2.0 KB
RevLine 
[25]1{-# LANGUAGE TypeFamilies #-}
2
[19]3module Lambda where
4
5import qualified Data.Supply as S
6import qualified Data.Char as C
[25]7import Control.Monad.IO.Class (MonadIO, liftIO)
8import Data.IORef (newIORef, readIORef, writeIORef)
[19]9
10{-
11 - Lambda calculus beagyazas
12 -}
13class 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 -}
21newtype Q a = Q { unQ :: a }
22instance 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]27eval :: Q a -> a
[19]28eval = unQ
29
30{-
31 - show interpreter
32 -}
[20]33showVar :: Int -> String -> String
[19]34showVar 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]39newtype S a = S { unS :: S.Supply Int -> Int -> ShowS }
[20]40
[19]41instance 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]52ast :: S a -> IO ShowS
[19]53ast a = do
54    s <- S.newSupply 0 (+1)
55    return $ unS a s 0
56
[20]57printAst :: S a -> IO ()
58printAst l = ast l >>= (\s -> putStrLn $ s "")
[25]59
60
61type family Sem (m :: * -> *) a :: *
62type instance Sem m Int      = Int
63type instance Sem m (a -> b) = m (Sem m a) -> m (Sem m b)
64
65newtype R m a = R { unR :: m (Sem m a) }
66
67share :: (MonadIO m) => m a -> m (m a)
68share 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
78instance (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)
Note: See TracBrowser for help on using the repository browser.