diff --git a/FRP/Moe.hs b/FRP/Moe.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Moe.hs
@@ -0,0 +1,5 @@
+module FRP.Moe (module FRP.Moe, module Control.Arrow, module FRP.Moe.Core, module FRP.Moe.Combinators) where
+
+import FRP.Moe.Core
+import FRP.Moe.Combinators
+import Control.Arrow
diff --git a/FRP/Moe/Combinators.hs b/FRP/Moe/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Moe/Combinators.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE Arrows #-}
+
+module FRP.Moe.Combinators where
+
+import Prelude hiding (cycle)
+import FRP.Moe.Core
+import Control.Arrow
+import System.Random
+
+sfConst :: a -> SF b a
+-- ^ Input:  <i1, i2, ...> (ignored)
+
+-- ^ Output: <x,  x,  ...>
+sfConst x = arr (const x)
+
+time :: SF () Double
+-- ^ Input:  <(), (), ...>
+
+-- ^ Outputs the sequence of the current time at each sample point
+time = sfConst 1 >>> integral
+
+noise :: (Random a, RandomGen b) => b -> SF () a
+-- ^ Input:  <i1, i2, ...> (ignored)
+
+-- ^ Outputs a sequence of random generated numbers using g0
+noise g0 = proc () -> do rec let (x, g') = random g
+                             g <- delay g0 -< g'
+                         returnA -< x
+
+noiseR :: (Random a, RandomGen b) => (a, a) -> b -> SF () a
+-- ^ Input:  <i1, i2, ...> (ignored)
+
+-- ^ Outputs a sequence of random generated numbers using g0, with lh
+
+-- ^ indicating the minimum and maximum numbers that are allowed.
+noiseR lh g0 = proc () -> do rec let (x, g') = randomR lh g
+                                 g <- delay g0 -< g'
+                             returnA -< x
+
+rep :: Int -> SF a a -> SF a a
+-- ^ rep n sf = sf >>> sf >>> ... >>> sf (n times)
+rep 0 sf = arr (\x -> x)
+rep n sf = sf >>> rep (n - 1) sf
+
+cycle :: [a] -> SF () a
+-- ^ xs:     [x1, x2, x3]
+
+-- ^ Input:  <(), (), (), (), (), ...>
+
+-- ^ Output: <x1, x2, x3, x1, x2, ...>
+cycle [] = error "Cycle: list is empty."
+cycle xs = proc () -> do rec let (y : ys) = zs
+                             zs <- delay xs -< case ys of
+                                                 [] -> xs
+                                                 _ -> ys
+                         returnA -< y
+
+timedCycle :: [(DTime, a)] -> SF () a
+timedCycle [] = error "TimedCycle: list is empty."
+timedCycle txs = auxCycle txs where
+           auxCycle ((timeOut, x) : txs') = dswitch aux (\_ -> if null txs' 
+                                                               then auxCycle txs
+                                                               else auxCycle txs') where
+                                              aux = proc () -> do t <- time -< ()
+                                                                  returnA -< (x, if t > timeOut
+                                                                                 then Event ()
+                                                                                 else NoEvent)
+
+data MemOp a = Read | Write a
+
+memory :: a -> SF (MemOp a) a
+-- ^ Input:  <Read, Write x1, Read, ...>
+
+-- ^ Output: <x0,   x1,       x1,   ...>
+memory x0 = proc op -> do rec let y = case op of
+                                        Read -> z
+                                        Write y' -> y'
+                              z <- delay x0 -< y
+                          returnA -< y
+
+stateful :: (a -> a) -> a -> SF () a
+-- ^ Input:  <(), (), (), ...>
+
+-- ^ Output: <x0, f x0, f (f x0), ...>
+stateful f x0 = proc () -> do rec let z = f y
+                                  y <- delay x0 -< z
+                              returnA -< y
+
+stateful2 :: (a -> b -> a) -> a -> SF b a
+-- ^ Input:  <i1, i2, i3, ...>
+
+-- ^ Output: <x0, f x0 i1, f (f x0 i1) i2, ...>
+stateful2 f x0 = proc i -> do rec let z = f y i
+                                  y <- delay x0 -< z
+                              returnA -< y
+                      
+integral :: SF Double Double
+-- ^ Simple integration
+integral = proc x -> do dt <- dTime -< ()
+                        rec let y = i + x * dt
+                            i <- delay 0 -< y
+                        returnA -< i
+
+broadcast :: Functor col => col sf -> a -> col (a, sf)
+broadcast sfs x = fmap ((,) x) sfs
diff --git a/FRP/Moe/Core.hs b/FRP/Moe/Core.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Moe/Core.hs
@@ -0,0 +1,385 @@
+{-# LANGUAGE Arrows, RankNTypes #-}
+module FRP.Moe.Core where
+
+import Prelude hiding ((.))
+import Data.Monoid
+import Data.Functor
+import Control.Category
+import Control.Applicative
+import Control.Arrow
+
+type DTime = Double
+
+-- | SF a b can be seen as a function from [x1, x2, ...] to [y1, y2, ...], in which
+
+-- | x1, x2, ... have the type of a, and y1, y2, ... have the type of b. Notice that 
+
+-- | each value is in fact a sample of a continuous temporal function of values in 
+
+-- | some certain time. The time stamps are omitted in most of the comments.
+newtype SF a b = MkSF {runSF :: DTime -> a -> (b, SF a b)}
+
+sfId :: SF a a
+-- ^ Input:  [x1, x2, ...]
+
+-- ^ Output: [x1, x2, ...]
+sfId = MkSF (\dt x -> (x, sfId))
+
+sfArr :: (a -> b) -> SF a b
+-- ^ Input: [x1, x2, ...]
+
+-- ^ Output: [f x1, f x2, ...]
+sfArr f = sf where sf = MkSF (\dt x -> (f x, sf))
+
+sfComp :: SF b c -> SF a b -> SF a c
+-- ^ Input of sf1:  [y1, y2, ...]
+
+-- ^ Output of sf1: [z1, z2, ...]
+
+-- ^ Input of sf2:  [x1, x2, ...]
+
+-- ^ Output of sf2: [y1, y2, ...]
+
+-- ^ Input:         [x1, x2, ...]
+
+-- ^ Output:        [z1, z2, ...]
+sfComp sf1 sf2 = MkSF (\dt x -> let (y, sf2') = runSF sf2 dt x
+                                    (z, sf1') = runSF sf1 dt y
+                                in (z, sfComp sf1' sf2'))
+
+sfLoop :: SF (a, c) (b, c) -> SF a b
+-- ^ Returns a signal function that:
+
+-- ^ Input:        [x1, x2, ...]
+
+-- ^ Output:       [y1, y2, ...]
+
+-- ^ whenever the following property holds for sf:
+
+-- ^ Input of sf:  [(x1, z1), (x2, z2), ...]
+
+-- ^ Output of sf: [(y1, z1), (y2, z2), ...]
+sfLoop sf = MkSF (\dt x -> let ((y, z), sf') = runSF sf dt (x, z)
+                           in (y, sfLoop sf'))
+
+sfFirst :: SF a b -> SF (a, c) (b, c)
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [y1, y2, ...]
+
+-- ^ Input:        [(x1, z1), (x2, z2), ...]
+
+-- ^ Output:       [(y1, z1), (y2, z2), ...]
+sfFirst sf = MkSF (\dt (x, y) -> let (z, sf') = runSF sf dt x
+                                 in ((z, y), sfFirst sf'))
+  
+sfSecond :: SF a b -> SF (c, a) (c, b)
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [y1, y2, ...]
+
+-- ^ Input:        [(z1, x1), (z2, x2), ...]
+
+-- ^ Output:       [(z1, y1), (z2, y2), ...]
+sfSecond sf = MkSF (\dt (x, y) -> let (z, sf') = runSF sf dt y
+                                  in ((x, z), sfSecond sf'))
+
+sfLeft :: SF a b -> SF (Either a c) (Either b c)              
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [y1, y2, ...]
+
+-- ^ Input:        [Left x1, Right z1, Left x2, ...]
+
+-- ^ Output:       [Left y1, Right z1, Left y2, ...]
+sfLeft sf = MkSF (\dt xy -> case xy of
+                     Left x -> let (z, sf') = runSF sf dt x
+                               in (Left z, sfLeft sf')
+                     Right y -> (Right y, sfLeft sf))
+            
+sfRight :: SF a b -> SF (Either c a) (Either c b)            
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [y1, y2, ...]
+
+-- ^ Input:        [Right x1, Left z1, Right x2, ...]
+
+-- ^ Output:       [Right y1, Left z2, Right y2, ...]
+sfRight sf = MkSF (\dt xy -> case xy of
+                      Left x -> (Left x, sfRight sf)
+                      Right y -> let (z, sf') = runSF sf dt y
+                                 in (Right z, sfRight sf'))
+
+sfDelay :: a -> SF a a
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [x0, x1, x2, ...]
+sfDelay x0 = MkSF (\dt x -> (x0, sfDelay x))
+
+dTime :: SF () DTime
+-- ^ Input of sf:  [x1, x2, ...]
+
+-- ^ Output of sf: [dt1, dt2, ...] (dt_i is the time interval between x_(i-1) and x_i)
+dTime = MkSF (\dt x -> (dt, dTime))
+
+instance Monoid b => Monoid (SF a b) where
+  mempty = sfArr (\_ -> mempty)
+  mappend sf1 sf2 = mappend <$> sf1 <*> sf2
+
+instance Functor (SF a) where
+  -- ^ Input of sf:  [x1, x2, ...]
+
+  -- ^ Output of sf: [y1, y2, ...]
+
+  -- ^ Input:        [x1, x2, ...]
+
+  -- ^ Output:       [f y1, f y2, ...]
+  fmap f sf = MkSF (\dt x -> let (y, sf') = runSF sf dt x
+                             in (f y, fmap f sf'))
+
+instance Applicative (SF a) where
+  -- ^ Input:  [i1, i2, ...] (ignored)
+
+  -- ^ Output: [x,  x,  ...]         
+  pure x = sfArr (const x)
+  -- ^ Input of sff:  [x1, x2, ...]
+
+  -- ^ Output of sff: [f1, f2, ...]
+
+  -- ^ Input of sfy:  [x1, x2, ...]
+
+  -- ^ Output of sfy: [y1, y2, ...]
+
+  -- ^ Input:         [x1, x2, ...]
+
+  -- ^ Output:        [f1 y1, f2 y2, ...]
+  sff <*> sfy = MkSF (\dt x -> let (f, sff') = runSF sff dt x
+                                   (y, sfy') = runSF sfy dt x
+                               in (f y, sff' <*> sfy'))
+
+instance Category SF where
+  id = sfId
+  (.) = sfComp
+
+-- ^ second, (&&&) and (***) are not necessary. They exist only for optimization
+instance Arrow SF where  
+  arr = sfArr
+  first = sfFirst
+  second = sfSecond
+  -- ^ Input of sf1:  [x1, x2, ...]
+
+  -- ^ Output of sf1: [y1, y2, ...]
+
+  -- ^ Input of sf2:  [x1, x2, ...]
+
+  -- ^ Output of sf2: [z1, z2, ...]
+
+  -- ^ Input:         [x1, x2, ...]
+
+  -- ^ Output:        [(y1, z1), (y2, z2), ...]
+  sf1 &&& sf2 = MkSF (\dt x -> let (y, sf1') = runSF sf1 dt x
+                                   (z, sf2') = runSF sf2 dt x
+                               in ((y, z), sf1' &&& sf2'))
+  -- ^ Input of sf1:  [x1, x2, ...]
+
+  -- ^ Output of sf1: [y1, y2, ...]
+
+  -- ^ Input of sf2:  [u1, u2, ...]
+
+  -- ^ Output of sf2: [z1, z2, ...]
+
+  -- ^ Input:         [(x1, u1), (x2, u2), ...]
+
+  -- ^ Output:        [(y1, z1), (y2, z2), ...]
+  sf1 *** sf2 = MkSF (\dt (x, y) -> let (z, sf1') = runSF sf1 dt x
+                                        (u, sf2') = runSF sf2 dt y
+                                    in ((z, u), sf1' *** sf2'))
+  
+instance ArrowLoop SF where  
+  loop = sfLoop
+  
+class Arrow a => ArrowDelay a where
+  delay :: b -> a b b
+  
+instance ArrowDelay SF where
+  delay = sfDelay
+  
+-- ^ right, (|||) and (+++) are not necessary. They exist only for optimization
+instance ArrowChoice SF where  
+  left = sfLeft
+  right = sfRight
+  -- ^ Input of sf1:  [x1, x2, ...]
+
+  -- ^ Output of sf1: [y1, y2, ...]
+
+  -- ^ Input of sf2:  [u1, u2, ...]
+
+  -- ^ Output of sf2: [z1, z2, ...]
+
+  -- ^ Input:         [Left x1, Right u1, Left x2, ...]
+
+  -- ^ Output:        [y1, z1, y2, ...]
+  sf1 ||| sf2 = MkSF (\dt xy -> case xy of
+                         Left x -> let (z, sf1') = runSF sf1 dt x
+                                   in (z, sf1' ||| sf2)
+                         Right y -> let (z, sf2') = runSF sf2 dt y
+                                    in (z, sf1 ||| sf2'))
+  -- ^ Input of sf1:  [x1, x2, ...]
+
+  -- ^ Output of sf1: [y1, y2, ...]
+
+  -- ^ Input of sf2:  [u1, u2, ...]
+
+  -- ^ Output of sf2: [z1, z2, ...]
+
+  -- ^ Input:         [Left x1, Right u1, Left x2, ...]
+
+  -- ^ Output:        [Left y1, Right z1, Left y2, ...]
+  sf1 +++ sf2 = MkSF (\dt xy -> case xy of
+                         Left x -> let (z, sf1') = runSF sf1 dt x
+                                   in (Left z, sf1' +++ sf2)
+                         Right y -> let (z, sf2') = runSF sf2 dt y
+                                    in (Right z, sf1 +++ sf2'))
+
+data Event a = Event a | NoEvent
+
+switch :: SF b (c, Event d) -> (d -> SF b c) -> SF b c
+-- ^ Input of sf:       [x1, x2, x3, ...]
+
+-- ^ Output of sf:      [(y1, NoEvent), (y2, Event e1), (y3, NoEvent), ...]
+
+-- ^ Input of (gen e):  [x2, x3, ...]
+
+-- ^ Output of (gen e): [y(e1)1, y(e1)2, ...]
+
+-- ^ Input:             [x1, x2, x3, ...]
+
+-- ^ Output:            [y1, y(e1)1, y(e1)2, ...]
+switch sf gen = MkSF (\dt x -> let ((y, ev), sf') = runSF sf dt x
+                               in case ev of
+                                 NoEvent -> (y, switch sf' gen)
+                                 Event e -> runSF (gen e) dt x)
+
+dswitch :: SF b (c, Event d) -> (d -> SF b c) -> SF b c
+-- ^ Input of sf:       [x1, x2, x3, ...]
+
+-- ^ Output of sf:      [(y1, NoEvent), (y2, Event e1), (y3, NoEvent), ...]
+
+-- ^ Input of (gen e):  [x2, x3, ...]
+
+-- ^ Output of (gen e): [y(e1)1, y(e1)2, ...]
+
+-- ^ Input:             [x1, x2, x3, ...]
+
+-- ^ Output:            [y1, y2, y(e1)2, ...]
+dswitch sf gen = MkSF (\dt x -> let ((y, ev), sf') = runSF sf dt x
+                                in case ev of
+                                  NoEvent -> (y, dswitch sf' gen)
+                                  Event e -> (y, snd (runSF (gen e) dt x)))
+                 
+kswitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b
+-- ^ Input of sf:            [x1, x2, x3, ...]
+
+-- ^ Output of sf:           [y1, y2, y3, ...]
+
+-- ^ Input of sfe:           [(x1, y1), (x2, y2), (x3, y3), ...]
+
+-- ^ Output of sfe:          [NoEvent, Event e1, NoEvent, ...]
+
+-- ^ Input of (gen sf3 e1):  [x2, x3, ...]
+
+-- ^ Output of (gen sf3 e1): [y(sf3,e1)1, y(sf3,e1)2, ...]
+
+-- ^ Input:                  [x1, x2, x3, ...]
+
+-- ^ Output:                 [y1, y(sf3,e1)1, y(sf3,e2)2, ...]
+
+-- ^ where sf1 = [x1, x2, x3, ...] -- ^> [y1, y2, y3, ...]
+
+-- ^       sf2 =     [x2, x3, ...] -- ^>     [y2, y3, ...]
+
+-- ^       sf3 =         [x3, ...] -- ^>         [y3, ...]
+
+-- ^       ...         
+kswitch sf sfe gen = MkSF (\dt x -> let (y, sf') = runSF sf dt x
+                                        (ev, sfe') = runSF sfe dt (x, y)
+                                    in case ev of
+                                      NoEvent -> (y, kswitch sf' sfe' gen)
+                                      Event e -> runSF (gen sf' e) dt x)
+
+dkswitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b
+-- ^ Input of sf:            [x1, x2, x3, ...]
+
+-- ^ Output of sf:           [y1, y2, y3, ...]
+
+-- ^ Input of sfe:           [(x1, y1), (x2, y2), (x3, y3), ...]
+
+-- ^ Output of sfe:          [NoEvent, Event e1, NoEvent, ...]
+
+-- ^ Input of (gen sf3 e1):  [x2, x3, ...]
+
+-- ^ Output of (gen sf3 e1): [y(sf3,e1)1, y(sf3,e1)2, ...]
+
+-- ^ Input:                  [x1, x2, x3, ...]
+
+-- ^ Output:                 [y1, y2, y(sf3,e2)2, ...]
+
+-- ^ where sf1 = [x1, x2, x3, ...] -- ^> [y1, y2, y3, ...]
+
+-- ^       sf2 =     [x2, x3, ...] -- ^>     [y2, y3, ...]
+
+-- ^       sf3 =         [x3, ...] -- ^>         [y3, ...]
+
+-- ^       ...         
+dkswitch sf sfe gen = MkSF (\dt x -> let (y, sf') = runSF sf dt x
+                                         (ev, sfe') = runSF sfe dt (x, y)
+                                     in case ev of
+                                       NoEvent -> (y, dkswitch sf' sfe' gen)
+                                       Event e -> (y, snd (runSF (gen sf' e) dt x)))
+                      
+pswitch :: Functor col => 
+           (forall sf. a -> col sf -> col (b, sf)) -> 
+           col (SF b c) -> 
+           SF (a, col c) (Event d) -> 
+           (col (SF b c) -> d -> SF a (col c)) ->
+           SF a (col c)
+pswitch route sfs sfe gen = MkSF (\dt x -> let ysfs = route x sfs
+                                               zssfs = fmap (\(y, sf) -> runSF sf dt y) ysfs
+                                               zs = fmap fst zssfs
+                                               sfs' = fmap snd zssfs
+                                               (e, sfe') = runSF sfe dt (x, zs)
+                                           in case e of
+                                             NoEvent -> (zs, pswitch route sfs' sfe' gen)
+                                             Event ev -> runSF (gen sfs' ev) dt x)
+                      
+dpswitch :: Functor col => 
+           (forall sf. a -> col sf -> col (b, sf)) -> 
+           col (SF b c) -> 
+           SF (a, col c) (Event d) -> 
+           (col (SF b c) -> d -> SF a (col c)) ->
+           SF a (col c)
+dpswitch route sfs sfe gen = MkSF (\dt x -> let ysfs = route x sfs
+                                                zssfs = fmap (\(y, sf) -> runSF sf dt y) ysfs
+                                                zs = fmap fst zssfs
+                                                sfs' = fmap snd zssfs
+                                                (e, sfe') = runSF sfe dt (x, zs)
+                                            in case e of
+                                              NoEvent -> (zs, dpswitch route sfs' sfe' gen)
+                                              Event ev -> (zs, snd (runSF (gen sfs' ev) dt x)))
+
+nth :: Int -> DTime -> SF () a -> a
+-- ^ Get the element (x_n) the output [y1, y2, ...] of sf.
+
+-- ^ Time interval is fixed to (dt).
+nth n dt sf = let f = runSF sf
+                  (x, sf') = f dt ()
+              in if n == 0 
+                 then x 
+                 else x `seq` nth (n - 1) dt sf'
+
+gen :: SF a b -> [(DTime, a)] -> [b]
+-- ^ Turn sf into a stream function.
+gen sf [] = []
+gen sf ((dt, x) : dtxs) = let f = runSF sf
+                              (y, sf') = f dt x
+                          in y `seq` (y : gen sf' dtxs)
diff --git a/FRP/MoeExample.hs b/FRP/MoeExample.hs
new file mode 100644
--- /dev/null
+++ b/FRP/MoeExample.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE NoMonomorphismRestriction, Arrows #-}
+import Control.Applicative
+import Control.Arrow
+import Data.Monoid
+import FRP.MoePure
+import FRP.MoeGLUT
+import Graphics.UI.GLUT
+
+white = Color3 1 1 1 :: Color3 GLfloat
+
+red = Color3 1 0 0
+
+green = Color3 0 1 0
+
+blue = Color3 0 0 1
+
+-- Rate of acceleration.
+g = 200
+
+-- X position of the ground.
+xGround = 200
+
+-- A ball falling with gravity.
+fallingBall (x0, v0) = proc () -> do v <- arr (+ v0) <<< integral -< g
+                                     x <- arr (+ x0) <<< integral -< v
+                                     returnA -< (x, v)
+
+-- If the ball hits the ground, reverses the velocity to let it bounce.
+hit (x, v) = (x, if x >= xGround && v > 0 then Event (x, -v) else NoEvent)
+
+-- Example for the (dswitch) combinator.
+bouncingBall xv0 = dswitch (fallingBall xv0 >>> arr hit) bouncingBall
+
+-- Example for the (timedCycle) combinator.
+coloredBouncingBall :: (Double, Double) -> SF () (Color3 GLfloat, Double)
+coloredBouncingBall xv0 = timedCycle [(interval, green), (interval, red), (interval, blue)] &&&
+                                     bouncingBall xv0 where
+                                      interval = 0.5
+
+-- Example for the (dkswitch) combinator.
+bouncingBall2 xv0 = dkswitch (bouncingBall xv0 >>> arr (\x -> [x]))
+                             (arr (\((), (x : _)) -> if x > xGround then Event () else NoEvent))
+                             (\sfs _ -> mappend (bouncingBall2 xv0) sfs)
+
+drawPoly ps = renderPrimitive Polygon $ mapM_ vertex ps 
+
+drawBall :: GLdouble -> GLdouble -> GLdouble -> IO ()
+drawBall r x0 y0 = mapM_ (\th -> drawPoly [Vertex2 x0 y0, 
+                                           Vertex2 (x0 + r * cos th) (y0 + r * sin th),
+                                           Vertex2 (x0 + r * cos (th + dth)) (y0 + r * sin (th + dth))]) 
+                   $ [0,dth..2*pi] where dth = 0.1*pi
+                   
+              
+output (x, (c, x'), xs) = do color white
+                             drawBall 20 100 (300 - realToFrac x)
+                             color c
+                             drawBall 20 200 (300 - realToFrac x)
+                             color white
+                             mapM_ (\(i, x) -> drawBall 20 (300 + 20*i) (300 - realToFrac x)) (zip [0,1..] $ reverse xs)
+
+example = liftA3 (,,) 
+                 (bouncingBall (0, 0))
+                 (coloredBouncingBall (0, 0))
+                 (bouncingBall2 (0, 0))
+
+main = start 20 (sfConst () >>> example) (0, (green, 0), [0]) output
diff --git a/FRP/MoeGLUT.hs b/FRP/MoeGLUT.hs
new file mode 100644
--- /dev/null
+++ b/FRP/MoeGLUT.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE FlexibleInstances, RankNTypes #-}
+module FRP.MoeGLUT (module FRP.MoeGLUT,
+                    module Graphics.UI.GLUT) where
+
+import FRP.Moe.Core
+import Control.Arrow
+import Data.IORef
+import Graphics.UI.GLUT
+
+type Time = Int
+
+type Input = Maybe (Key, KeyState, Modifiers, Position)
+
+type Prog b = SF Input b
+
+type Handle b = IORef (Prog b, Time, b)
+
+timer :: Handle b -> Int -> (b -> IO ()) -> IdleCallback
+timer r tick act = do clear [ColorBuffer]
+                      (sf, t, y) <- readIORef r
+                      t' <- get elapsedTime
+                      let deltat = t' - t
+                          timeOut = tick * 2
+                          deltat' = if deltat < timeOut then deltat else timeOut
+                          dt = fromIntegral deltat' / 1000
+                          (y, sf') = runSF sf dt Nothing
+                      writeIORef r (sf', t', y)
+                      print deltat'
+                      addTimerCallback tick (timer r tick act)                      
+                      act y
+                      swapBuffers
+
+                
+keyMouse :: Handle b -> KeyboardMouseCallback
+keyMouse r k ks mod pos = do (sf, t, _) <- readIORef r
+                             t' <- get elapsedTime
+                             let (y, sf') = runSF sf (fromIntegral (t' - t) / 1000) (Just (k, ks, mod, pos))
+                             y `seq` writeIORef r (sf', t', y)
+                             
+defaultReshape :: ReshapeCallback
+defaultReshape size@(Size w h) = do
+   viewport $= (Position 0 0, size)
+   matrixMode $= Projection
+   loadIdentity
+   ortho2D 0 (fromIntegral w) 0 (fromIntegral h)
+   matrixMode $= Modelview 0
+
+data DisplaySetup = DisplaySetup {displayTitle :: String,
+                                  displayMode :: [DisplayMode],
+                                  displaySize :: Size,
+                                  displayPosition :: Position,
+                                  displayColor :: Color4 GLclampf,
+                                  displayReshape :: ReshapeCallback,
+                                  displayInit :: (String, [String]) -> IO ()
+                                  }
+
+defaultDisplaySetup = DisplaySetup {displayTitle = "moeDefault",
+                                    displayMode = [DoubleBuffered, RGBAMode],
+                                    displaySize = Size 800 600,
+                                    displayPosition = Position 0 0,
+                                    displayColor = Color4 0 0 0 0,
+                                    displayReshape = defaultReshape,
+                                    displayInit = const $ return ()
+                                    }                                   
+
+startProg :: DisplaySetup -> Int -> Prog b -> b -> (b -> IO ()) -> IO ()
+startProg ds tick sf y0 act =  let title = displayTitle ds
+                                   mode = displayMode ds
+                                   size = displaySize ds
+                                   position = displayPosition ds
+                                   color = displayColor ds
+                                   reshape = displayReshape ds
+                                   init = displayInit ds
+                                in do nameAndArgs <- getArgsAndInitialize
+                                      initialDisplayMode $= mode
+                                      initialWindowSize $= size
+                                      initialWindowPosition $= position
+                                      createWindow title
+                                      clearColor $= color
+                                      init nameAndArgs
+                                      t0 <- get elapsedTime
+                                      r <- newIORef (sf, t0, y0)
+                                      reshapeCallback $= Just reshape
+                                      keyboardMouseCallback $= Just (keyMouse r)
+                                      addTimerCallback tick (timer r tick act)
+                                      displayCallback $= return ()
+                                      mainLoop                                   
+
+start = startProg defaultDisplaySetup
diff --git a/FRP/MoePure.hs b/FRP/MoePure.hs
new file mode 100644
--- /dev/null
+++ b/FRP/MoePure.hs
@@ -0,0 +1,5 @@
+module FRP.MoePure (module FRP.MoePure, module Control.Arrow, module FRP.Moe.Core, module FRP.Moe.Combinators) where
+
+import FRP.Moe.Core hiding (dTime, sfDelay, delay, MkSF)
+import FRP.Moe.Combinators hiding (cycle, stateful, stateful2)
+import Control.Arrow
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) <2011>, <Xinyu Jiang>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the <organization> nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Moe.cabal b/Moe.cabal
new file mode 100644
--- /dev/null
+++ b/Moe.cabal
@@ -0,0 +1,19 @@
+Name:                Moe
+Version:             0.1
+Description:         A FRP library based on signal functions.
+License:             BSD3
+License-file:        LICENSE
+Author:              Xinyu Jiang
+Maintainer:          fnnirvana@gmail.com
+Category:            FRP
+Synopsis:         A FRP library based on signal functions.
+Build-Type:          Simple
+Cabal-Version:       >=1.2
+
+Library
+  Exposed-Modules:   FRP.Moe, FRP.MoePure, FRP.MoeGLUT FRP.Moe.Core FRP.Moe.Combinators
+  Build-Depends:     base >=3 && <5, random, GLUT
+
+Executable MoeExample
+  Main-Is:           FRP/MoeExample.hs
+  Build-Depends:     base, random, GLUT
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
