packages feed

Rattus 0.3.1 → 0.4

raw patch · 15 files changed

+399/−290 lines, 15 filesdep +ghc-primdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: ghc-prim

Dependency ranges changed: base

API changes (from Hackage documentation)

- Rattus: (<**) :: Stable a => O (a -> b) -> a -> O b
- Rattus: (<*>) :: O (a -> b) -> O a -> O b
- Rattus: (|**) :: Stable a => Box (a -> b) -> a -> Box b
- Rattus: (|*|) :: Box (a -> b) -> Box a -> Box b
- Rattus.Event: Now :: !a -> Event a
- Rattus.Event: Wait :: !O (Event a) -> Event a
- Rattus.Event: await :: (Stable a, Stable b) => Event a -> Event b -> Event (a :* b)
- Rattus.Event: data Event a
- Rattus.Event: whenJust :: Str (Maybe' a) -> Str (Event a)
- Rattus.Events: map :: Box (a -> b) -> Events a -> Events b
- Rattus.Events: never :: Events a
- Rattus.Events: switch :: Str a -> Events (Str a) -> Str a
- Rattus.Events: switchTrans :: (Str a -> Str b) -> Events (Str a -> Str b) -> Str a -> Str b
- Rattus.Events: trigger :: Box (a -> Bool) -> Str a -> Events a
- Rattus.Events: triggerMap :: Box (a -> Maybe' b) -> Str a -> Events b
- Rattus.Events: type Events a = Str (Maybe' a)
+ Rattus: (<##) :: Stable a => O (a -> b) -> a -> O b
+ Rattus: (<#>) :: O (a -> b) -> O a -> O b
+ Rattus: (|##) :: Stable a => Box (a -> b) -> a -> Box b
+ Rattus: (|#|) :: Box (a -> b) -> Box a -> Box b
+ Rattus.Event: type Event a = Str (Maybe' a)
+ Rattus.Future: Now :: !a -> Future a
+ Rattus.Future: Wait :: !O (Future a) -> Future a
+ Rattus.Future: await :: (Stable a, Stable b) => Future a -> Future b -> Future (a :* b)
+ Rattus.Future: data Future a
+ Rattus.Future: map :: Box (a -> b) -> Future a -> Future b
+ Rattus.Future: never :: Future a
+ Rattus.Future: switch :: Str a -> Future (Str a) -> Str a
+ Rattus.Future: switchTrans :: (Str a -> Str b) -> Future (Str a -> Str b) -> Str a -> Str b
+ Rattus.Future: trigger :: Box (a -> Bool) -> Str a -> Future a
+ Rattus.Future: triggerMap :: Box (a -> Maybe' b) -> Str a -> Future b
+ Rattus.Future: whenJust :: Str (Maybe' a) -> Str (Future a)
- Rattus.Yampa: (>>>) :: Category cat => cat a b -> cat b c -> cat a c
+ Rattus.Yampa: (>>>) :: forall k cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c

Files

CHANGELOG.md view
@@ -1,3 +1,23 @@+0.4+---++More general typing rules for delay, functions, and guarded recursion:++- delay and function definitions may now occur under a delay.+- Guarded recursive calls may occur at any time in the future -- not+  only exactly one time step into the future.+- As before, adv and recursive calls may only occur directly in the+  scope of delay. The scope of a delay is interrupted by adv, box,+  guarded recursive definitions, and function definitions.++Changes in the library:++- Rename applicative-style operators to avoid clash with Haskell's <*>+  operator.+- Rename types: Event -> Future; Events -> Event+++ 0.3.1 ----- 
Rattus.cabal view
@@ -1,6 +1,6 @@ cabal-version:       1.18 name:                Rattus-version:             0.3.1+version:             0.4 category:            FRP synopsis:            A modal FRP language description:@@ -139,7 +139,7 @@                        Rattus.Stream                        Rattus.Strict                        Rattus.Event-                       Rattus.Events+                       Rattus.Future                        Rattus.ToHaskell                        Rattus.Yampa                        @@ -153,7 +153,7 @@                        Rattus.Plugin.Utils                        Rattus.Plugin.Dependency                        Rattus.Plugin.StableSolver-  build-depends:       base >=4.12 && <5, containers, simple-affine-space, ghc >= 8.6 && < 8.11+  build-depends:       base >=4.12 && <5, containers, ghc >= 8.6 && < 8.11, ghc-prim, simple-affine-space   hs-source-dirs:      src   default-language:    Haskell2010   ghc-options:         -W@@ -180,7 +180,15 @@   main-is:             test/IllTyped.hs   default-language:    Haskell2010   build-depends:       Rattus, base-  ghc-options:         -fplugin=Rattus.Plugin -rtsopts+  ghc-options:         +                       -fplugin=Rattus.Plugin -rtsopts++Test-Suite newly-typed+  type:                exitcode-stdio-1.0+  main-is:             test/NewlyTyped.hs+  default-language:    Haskell2010+  build-depends:       Rattus, base+  ghc-options:         -fplugin=Rattus.Plugin   Test-Suite well-typed
docs/paper.pdf view

binary file changed (622063 → 660739 bytes)

src/Rattus.hs view
@@ -13,10 +13,10 @@   -- * Annotation   Rattus(..),   -- * Applicative operators-  (|*|),-  (|**),-  (<*>),-  (<**),+  (|#|),+  (|##),+  (<#>),+  (<##),   -- * box for stable types   box'   )@@ -26,32 +26,29 @@ import Rattus.Strict import Rattus.Primitives --import Prelude hiding ((<*>))- -- all functions in this module are in Rattus  {-# ANN module Rattus #-}   -- | Applicative operator for 'O'.-{-# INLINE (<*>) #-}-(<*>) :: O (a -> b) -> O a -> O b-f <*> x = delay (adv f (adv x))+{-# INLINE (<#>) #-}+(<#>) :: O (a -> b) -> O a -> O b+f <#> x = delay (adv f (adv x)) --- | Variant of '<*>' where the argument is of a stable type..-{-# INLINE (<**) #-}-(<**) :: Stable a => O (a -> b) -> a -> O b-f <** x = delay (adv f x)+-- | Variant of '<#>' where the argument is of a stable type..+{-# INLINE (<##) #-}+(<##) :: Stable a => O (a -> b) -> a -> O b+f <## x = delay (adv f x)  -- | Applicative operator for 'Box'.-{-# INLINE (|*|) #-}-(|*|) :: Box (a -> b) -> Box a -> Box b-f |*| x = box (unbox f (unbox x))+{-# INLINE (|#|) #-}+(|#|) :: Box (a -> b) -> Box a -> Box b+f |#| x = box (unbox f (unbox x)) --- | Variant of '|*|' where the argument is of a stable type..-{-# INLINE (|**) #-}-(|**) :: Stable a => Box (a -> b) -> a -> Box b-f |** x = box (unbox f x)+-- | Variant of '|#|' where the argument is of a stable type..+{-# INLINE (|##) #-}+(|##) :: Stable a => Box (a -> b) -> a -> Box b+f |## x = box (unbox f x)   -- | Variant of 'box' for stable types that can be safely used nested
src/Rattus/Event.hs view
@@ -1,17 +1,15 @@ {-# OPTIONS -fplugin=Rattus.Plugin #-}-{-# LANGUAGE TypeOperators #-} --- | Programming with single shot events, i.e. events that may occur at--- most once.+-- | Programming with many-shot events, i.e. events that may occur zero+-- or more times. + module Rattus.Event   ( map   , never   , switch   , switchTrans-  , whenJust-  , Event(..)-  , await+  , Event   , trigger   , triggerMap   )@@ -20,92 +18,59 @@  import Rattus import Rattus.Stream hiding (map)--import Prelude hiding ((<*>), map)+import qualified Rattus.Stream as Str +import Prelude hiding (map) --- | An event may either occur now or later.-data Event a = Now !a | Wait !(O (Event a))+-- | Events are simply streams of 'Maybe''s.+type Event a = Str (Maybe' a)  -- all functions in this module are in Rattus  {-# ANN module Rattus #-} --- | Apply a function to the value of the event (if it ever occurs).+-- | Apply a function to the values of the event (every time it occurs). {-# NOINLINE [1] map #-} map :: Box (a -> b) -> Event a -> Event b-map f (Now x) = Now (unbox f x)-map f (Wait x) = Wait (delay (map f) <*> x)+map f (Just' x ::: xs) =  (Just' (unbox f x)) ::: delay (map f (adv xs))+map f (Nothing' ::: xs) = Nothing' ::: delay (map f (adv xs))  -- | An event that will never occur. never :: Event a-never = Wait (delay never)-+never = Nothing' ::: delay never --- | @switch s e@ will behave like @s@ until the event @e@ occurs with--- value @s'@, in which case it will behave as @s'@.+-- | @switch s e@ will behave like @s@ but switches to @s'$ every time+-- the event 'e' occurs with some value @s'@. switch :: Str a -> Event (Str a) -> Str a-switch (x ::: xs) (Wait fas) = x ::: (delay switch <*> xs <*> fas)-switch _xs        (Now ys)   = ys ---- | Turn a stream of 'Maybe''s into an event. The event will occur--- whenever the stream has a value of the form @Just' v@, and the--- event then has value @v@.-firstJust :: Str (Maybe' a) -> Event a-firstJust (Just' x ::: _) = Now x-firstJust (Nothing' ::: xs) = Wait (delay firstJust <*> xs)---- | Turn a stream of 'Maybe''s into a stream of events. Each such--- event behaves as if created by 'firstJust'.-whenJust :: Str (Maybe' a) -> Str (Event a)-whenJust cur@(_ ::: xs) = firstJust cur ::: (delay whenJust <*> xs)+switch (x ::: xs) (Nothing' ::: fas) = x ::: delay (switch (adv xs)  (adv fas))+switch  _xs       (Just' (a ::: as) ::: fas)   = a ::: (delay switch <#> as <#> fas)   -- | Like 'switch' but works on stream functions instead of--- streams. That is, @switchTrans s e@ will behave like @s@ until the--- event @e@ occurs with value @s'@, in which case it will behave as+-- streams. That is, @switchTrans s e@ will behave like @s@ but+-- switches to @s'$ every time the event 'e' occurs with some value -- @s'@. switchTrans :: (Str a -> Str b) -> Event (Str a -> Str b) -> (Str a -> Str b) switchTrans f es as = switchTrans' (f as) es as  -- | Helper function for 'switchTrans'. switchTrans' :: Str b -> Event (Str a -> Str b) -> Str a -> Str b-switchTrans' (x ::: xs) (Wait fas) (_:::is) = x ::: (delay switchTrans' <*> xs <*> fas <*> is)-switchTrans' _xs        (Now ys)   is = ys is+switchTrans' (b ::: bs) (Nothing' ::: fs) (_:::as) = b ::: (delay switchTrans' <#> bs <#> fs <#> as)+switchTrans' _xs        (Just' f ::: fs)  as@(_:::as') = b' ::: (delay switchTrans' <#> bs' <#> fs <#> as')+  where (b' ::: bs') = f as --- | Helper function for 'await'.-await1 :: Stable a => a -> Event b -> Event (a :* b)-await1 a (Wait eb) = Wait (delay await1 <** a <*> eb)-await1 a (Now  b)  = Now  (a :* b) --- | Helper function for 'await'.-await2 :: Stable b => b -> Event a -> Event (a :* b)-await2 b (Wait ea) = Wait (delay await2 <** b <*> ea)-await2 b (Now  a)  = Now  (a :* b)---- | Synchronise two events. The resulting event occurs after both--- events have occurred (coinciding with whichever event occurred--- last.-await :: (Stable a, Stable b) => Event a -> Event b -> Event(a :* b)-await (Wait ea) (Wait eb)  = Wait (delay await <*> ea <*> eb)-await (Now a)   eb         = await1 a eb-await ea        (Now b)    = await2 b ea---- | Trigger an event as soon as the given predicate turns true on the--- given stream. The value of the event is the same as that of the+-- | Trigger an event as every time the given predicate turns true on+-- the given stream. The value of the event is the same as that of the -- stream at that time. trigger :: Box (a -> Bool) -> Str a -> Event a-trigger p (x ::: xs)-  | unbox p x  = Now x-  | otherwise  = Wait (delay (trigger p) <*> xs)-+trigger p (x ::: xs) = x' ::: (delay (trigger p) <#> xs)+  where x' = if unbox p x then Just' x else Nothing' --- | Trigger an event as soon as the given function produces a 'Just''+-- | Trigger an event every time the given function produces a 'Just'' -- value. triggerMap :: Box (a -> Maybe' b) -> Str a -> Event b-triggerMap f (x ::: xs) =-  case unbox f x of-    Just' y  -> Now y-    Nothing' -> Wait (delay (triggerMap f) <*> xs)+triggerMap = Str.map+  {-# RULES 
− src/Rattus/Events.hs
@@ -1,81 +0,0 @@-{-# OPTIONS -fplugin=Rattus.Plugin #-}---- | Programming with many-shot events, i.e. events that may occur zero--- or more times.---module Rattus.Events-  ( map-  , never-  , switch-  , switchTrans-  , Events-  , trigger-  , triggerMap-  )--where--import Rattus-import Rattus.Stream hiding (map)-import qualified Rattus.Stream as S--import Prelude hiding ((<*>), map)---- | Events are simply streams of 'Maybe''s.-type Events a = Str (Maybe' a)---- all functions in this module are in Rattus -{-# ANN module Rattus #-}---- | Apply a function to the values of the event (every time it occurs).-{-# NOINLINE [1] map #-}-map :: Box (a -> b) -> Events a -> Events b-map f (Just' x ::: xs) =  (Just' (unbox f x)) ::: delay (map f (adv xs))-map f (Nothing' ::: xs) = Nothing' ::: delay (map f (adv xs))---- | An event that will never occur.-never :: Events a-never = Nothing' ::: delay never---- | @switch s e@ will behave like @s@ but switches to @s'$ every time--- the event 'e' occurs with some value @s'@.-switch :: Str a -> Events (Str a) -> Str a-switch (x ::: xs) (Nothing' ::: fas) = x ::: delay (switch (adv xs)  (adv fas))-switch  _xs       (Just' (a ::: as) ::: fas)   = a ::: (delay switch <*> as <*> fas)----- | Like 'switch' but works on stream functions instead of--- streams. That is, @switchTrans s e@ will behave like @s@ but--- switches to @s'$ every time the event 'e' occurs with some value--- @s'@.-switchTrans :: (Str a -> Str b) -> Events (Str a -> Str b) -> (Str a -> Str b)-switchTrans f es as = switchTrans' (f as) es as---- | Helper function for 'switchTrans'.-switchTrans' :: Str b -> Events (Str a -> Str b) -> Str a -> Str b-switchTrans' (b ::: bs) (Nothing' ::: fs) (_:::as) = b ::: (delay switchTrans' <*> bs <*> fs <*> as)-switchTrans' _xs        (Just' f ::: fs)  as@(_:::as') = b' ::: (delay switchTrans' <*> bs' <*> fs <*> as')-  where (b' ::: bs') = f as----- | Trigger an event as every time the given predicate turns true on--- the given stream. The value of the event is the same as that of the--- stream at that time.-trigger :: Box (a -> Bool) -> Str a -> Events a-trigger p (x ::: xs) = x' ::: (delay (trigger p) <*> xs)-  where x' = if unbox p x then Just' x else Nothing'---- | Trigger an event every time the given function produces a 'Just''--- value.-triggerMap :: Box (a -> Maybe' b) -> Str a -> Events b-triggerMap = S.map----{-# RULES--  "map/map" forall f g xs.-    map f (map g xs) = map (box (unbox f . unbox g)) xs ;--#-}
+ src/Rattus/Future.hs view
@@ -0,0 +1,115 @@+{-# OPTIONS -fplugin=Rattus.Plugin #-}+{-# LANGUAGE TypeOperators #-}++-- | Programming with futures, i.e. data that will arrive at some time+-- in the future++module Rattus.Future+  ( map+  , never+  , switch+  , switchTrans+  , whenJust+  , Future(..)+  , await+  , trigger+  , triggerMap+  )++where++import Rattus+import Rattus.Stream hiding (map)++import Prelude hiding (map)+++-- | A future may either be available now or later.+data Future a = Now !a | Wait !(O (Future a))++-- all functions in this module are in Rattus +{-# ANN module Rattus #-}++-- | Apply a function to the value of the future (if it ever occurs).+{-# NOINLINE [1] map #-}+map :: Box (a -> b) -> Future a -> Future b+map f (Now x) = Now (unbox f x)+map f (Wait x) = Wait (delay (map f) <#> x)++-- | A future that will never happen.+never :: Future a+never = Wait (delay never)+++-- | @switch s e@ will behave like @s@ until the future @e@ is+-- available with value @s'@, in which case it will behave as @s'@.+switch :: Str a -> Future (Str a) -> Str a+switch (x ::: xs) (Wait fas) = x ::: (delay switch <#> xs <#> fas)+switch _xs        (Now ys)   = ys ++-- | Turn a stream of 'Maybe''s into a future. The future will occur+-- whenever the stream has a value of the form @Just' v@, and the+-- future then has value @v@.+firstJust :: Str (Maybe' a) -> Future a+firstJust (Just' x ::: _) = Now x+firstJust (Nothing' ::: xs) = Wait (delay firstJust <#> xs)++-- | Turn a stream of 'Maybe''s into a stream of futures. Each such+-- future behaves as if created by 'firstJust'.+whenJust :: Str (Maybe' a) -> Str (Future a)+whenJust cur@(_ ::: xs) = firstJust cur ::: (delay whenJust <#> xs)+++-- | Like 'switch' but works on stream functions instead of+-- streams. That is, @switchTrans s e@ will behave like @s@ until the+-- future @e@ occurs with value @s'@, in which case it will behave as+-- @s'@.+switchTrans :: (Str a -> Str b) -> Future (Str a -> Str b) -> (Str a -> Str b)+switchTrans f es as = switchTrans' (f as) es as++-- | Helper function for 'switchTrans'.+switchTrans' :: Str b -> Future (Str a -> Str b) -> Str a -> Str b+switchTrans' (x ::: xs) (Wait fas) (_:::is) = x ::: (delay switchTrans' <#> xs <#> fas <#> is)+switchTrans' _xs        (Now ys)   is = ys is++-- | Helper function for 'await'.+await1 :: Stable a => a -> Future b -> Future (a :* b)+await1 a (Wait eb) = Wait (delay await1 <## a <#> eb)+await1 a (Now  b)  = Now  (a :* b)++-- | Helper function for 'await'.+await2 :: Stable b => b -> Future a -> Future (a :* b)+await2 b (Wait ea) = Wait (delay await2 <## b <#> ea)+await2 b (Now  a)  = Now  (a :* b)++-- | Synchronise two futures. The resulting future occurs after both+-- futures have occurred (coinciding with whichever future occurred+-- last.+await :: (Stable a, Stable b) => Future a -> Future b -> Future(a :* b)+await (Wait ea) (Wait eb)  = Wait (delay await <#> ea <#> eb)+await (Now a)   eb         = await1 a eb+await ea        (Now b)    = await2 b ea++-- | Trigger a future as soon as the given predicate turns true on the+-- given stream. The value of the future is the same as that of the+-- stream at that time.+trigger :: Box (a -> Bool) -> Str a -> Future a+trigger p (x ::: xs)+  | unbox p x  = Now x+  | otherwise  = Wait (delay (trigger p) <#> xs)+++-- | Trigger a future as soon as the given function produces a 'Just''+-- value.+triggerMap :: Box (a -> Maybe' b) -> Str a -> Future b+triggerMap f (x ::: xs) =+  case unbox f x of+    Just' y  -> Now y+    Nothing' -> Wait (delay (triggerMap f) <#> xs)++{-# RULES++  "map/map" forall f g xs.+    map f (map g xs) = map (box (unbox f . unbox g)) xs ;++#-}
src/Rattus/Plugin/Dependency.hs view
@@ -7,7 +7,7 @@ -- (mutual) recursive. To this end, this module also provides a -- functions to compute, bound variables and variable occurrences. -module Rattus.Plugin.Dependency (dependency, HasBV (..)) where+module Rattus.Plugin.Dependency (dependency, HasBV (..),printBinds) where   import GhcPlugins@@ -58,16 +58,16 @@         filterJust (CyclicSCC bs) = Just (CyclicSCC (catMaybes bs))  --- printBinds (AcyclicSCC bind) = liftIO (putStr "acyclic bind: ") >> printBind (fst bind) >> liftIO (putStrLn "") --- printBinds (CyclicSCC binds) = liftIO (putStr "cyclic binds: ") >> mapM_ (printBind . fst) binds >> liftIO (putStrLn "") +printBinds (AcyclicSCC bind) = liftIO (putStr "acyclic bind: ") >> printBind (fst bind) >> liftIO (putStrLn "") +printBinds (CyclicSCC binds) = liftIO (putStr "cyclic binds: ") >> mapM_ (printBind . fst) binds >> liftIO (putStrLn "")   --- printBind (L _ FunBind{fun_id = L _ name}) = ---   liftIO $ putStr $ (getOccString name ++ " ")--- printBind (L _ (AbsBinds {abs_exports = exp})) = ---   mapM_ (\ e -> liftIO $ putStr $ ((getOccString $ abe_poly e)  ++ " ")) exp--- printBind (L _ (VarBind {var_id = name})) =   liftIO $ putStr $ (getOccString name ++ " ")--- printBind _ = return ()+printBind (L _ FunBind{fun_id = L _ name}) = +  liftIO $ putStr $ (getOccString name ++ " ")+printBind (L _ (AbsBinds {abs_exports = exp})) = +  mapM_ (\ e -> liftIO $ putStr $ ((getOccString $ abe_poly e)  ++ " ")) exp+printBind (L _ (VarBind {var_id = name})) =   liftIO $ putStr $ (getOccString name ++ " ")+printBind _ = return ()  -- | Computes the variables that are bound by a given piece of syntax. @@ -186,7 +186,10 @@  instance HasFV (HsValBindsLR GhcTc GhcTc) where   getFV (ValBinds _ b _) = getFV b-  getFV _ = Set.empty+  getFV (XValBindsLR b) = getFV b++instance HasFV (NHsValBindsLR GhcTc) where+  getFV (NValBinds bs _) = foldMap (getFV . snd) bs  instance HasFV (HsBindLR GhcTc GhcTc) where   getFV FunBind {fun_matches = ms} = getFV ms
src/Rattus/Plugin/ScopeCheck.hs view
@@ -19,6 +19,8 @@ import Rattus.Plugin.Dependency import Rattus.Plugin.Annotation +import Data.IORef+ import Prelude hiding ((<>)) import GhcPlugins import TcRnTypes@@ -41,25 +43,31 @@ import qualified Data.Map as Map import Data.Set (Set) import Data.Map (Map)+import Data.List import System.Exit+import Data.Either import Data.Maybe  import Control.Monad +type ErrorMsg = (Severity,SrcSpan,SDoc)+type ErrorMsgsRef = IORef [ErrorMsg]+ -- | The current context for scope checking data Ctxt = Ctxt   {+    errorMsgs :: ErrorMsgsRef,     -- | Variables that are in scope now (i.e. occurring in the typing     -- context but not to the left of a tick)     current :: LCtxt,     -- | Variables that are in the typing context, but to the left of a     -- tick-    earlier :: Maybe LCtxt,+    earlier :: Either NoTickReason LCtxt,     -- | Variables that have fallen out of scope. The map contains the     -- reason why they have fallen out of scope.     hidden :: Hidden,-    -- | Same as 'hidden' but for recursive variables.-    hiddenRec :: Hidden,+    -- -- | Same as 'hidden' but for recursive variables.+    -- hiddenRec :: Hidden,     -- | The current location information.     srcLoc :: SrcSpan,     -- | If we are in the body of a recursively defined function, this@@ -79,19 +87,19 @@     -- (stripped of all non-stable stuff). It is set when typechecking     -- 'box', 'arr' and guarded recursion.     stabilized :: Maybe StableReason}-  deriving Show  + -- | The starting context for checking a top-level definition. For -- non-recursive definitions, the argument is @Nothing@. Otherwise, it -- contains the recursively defined variables along with the location -- of the recursive definition.-emptyCtxt :: Maybe (Set Var,SrcSpan) -> Ctxt-emptyCtxt mvar =-  Ctxt { current =  Set.empty,-         earlier = Nothing,+emptyCtxt :: ErrorMsgsRef -> Maybe (Set Var,SrcSpan) -> Ctxt+emptyCtxt em mvar =+  Ctxt { errorMsgs = em,+         current =  Set.empty,+         earlier = Left NoDelay,          hidden = Map.empty,-         hiddenRec = Map.empty,          srcLoc = UnhelpfulSpan "<no location info>",          recDef = mvar,          primAlias = Map.empty,@@ -113,8 +121,11 @@ data StableReason = StableRec SrcSpan | StableBox | StableArr deriving Show  -- | Indicates, why a variable has fallen out of scope.-data HiddenReason = Stabilize StableReason | FunDef | AdvApp deriving Show+data HiddenReason = Stabilize StableReason | FunDef | DelayApp | AdvApp deriving Show +-- | Indicates, why there is no tick+data NoTickReason = NoDelay | TickHidden HiddenReason deriving Show+ -- | Hidden context, containing variables that have fallen out of -- context along with the reason why they have. type Hidden = Map Var HiddenReason@@ -138,7 +149,7 @@ -- variables. class ScopeBind a where   -- | 'checkBind' checks whether its argument is scope-correct and in--- addition returns the the set of variables bound by it.+  -- addition returns the the set of variables bound by it.   checkBind :: GetCtxt => a -> TcM (Bool,Set Var)  @@ -158,10 +169,20 @@ -- found, the current execution is halted with 'exitFailure'. checkAll :: TcGblEnv -> TcM () checkAll env = do-  let bindDep = filter (filterBinds (tcg_mod env) (tcg_ann_env env)) (dependency (tcg_binds env))-  res <- mapM checkSCC bindDep+  let dep = dependency (tcg_binds env)+  let bindDep = filter (filterBinds (tcg_mod env) (tcg_ann_env env)) dep+  err <- liftIO (newIORef [])+  res <- mapM (checkSCC err) bindDep+  msgs <- liftIO (readIORef err)+  printAccErrMsgs msgs   if and res then return () else liftIO exitFailure ++printAccErrMsgs :: [ErrorMsg] -> TcM ()+printAccErrMsgs msgs = mapM_ printMsg (sortOn (\(_,l,_)->l) msgs)+  where printMsg (sev,loc,doc) = printMessage sev loc doc++ -- | This function checks whether a given top-level definition (either -- a single non-recursive definition or a group of mutual recursive -- definitions) is marked as Rattus code (via an annotation). In a@@ -195,7 +216,7 @@  instance Scope a => Scope (Match GhcTc a) where   check Match{m_pats=ps,m_grhss=rhs} = mod `modifyCtxt` check rhs-    where mod c = addVars (getBV ps) (if null ps then c else stabilizeLater c)+    where mod c = addVars (getBV ps) (if null ps then c else stabilizeLater FunDef c)   check XMatch{} = return True  instance Scope a => Scope (MatchGroup GhcTc a) where@@ -251,13 +272,13 @@       _ -> return (res, vs)     where check' b@(L l _) = fc l `modifyCtxt` check b           fc l c = let-            ctxHid = maybe (current c) (Set.union (current c)) (earlier c)-            recHid = maybe ctxHid (Set.union ctxHid . fst) (recDef c)+            ctxHid = either (const $ current c) (Set.union (current c)) (earlier c)             in c {current = Set.empty,-                  earlier = Nothing,+                  earlier = Left (TickHidden $ Stabilize $ StableRec l),                   hidden =  hidden c `Map.union`-                            (Map.fromSet (const (Stabilize (StableRec l))) recHid),-                  recDef = Just (vs,l),+                            (Map.fromSet (const (Stabilize (StableRec l))) ctxHid),+                  recDef = maybe (Just (vs,l)) (\(vs',_) -> Just (Set.union vs' vs,l)) (recDef c),+                   -- TODO fix location info of recDef (needs one location for each var)                   stabilized = Just (StableRec l)}            recReason :: StableReason -> SDoc@@ -324,6 +345,14 @@ arrReason StableBox = "The use of arr in the scope of box" arrReason (StableRec _) = "The use of arr in a recursive definition" +tickHidden :: HiddenReason -> SDoc+tickHidden FunDef = "a function definition"+tickHidden DelayApp = "a nested application of delay"+tickHidden AdvApp = "an application of adv"+tickHidden (Stabilize StableBox) = "an application of box"+tickHidden (Stabilize StableArr) = "an application of arr"+tickHidden (Stabilize (StableRec src)) = "a nested recursive definition (at " <> ppr src <> ")"+ instance Scope (HsExpr GhcTc) where   check (HsVar _ (L _ v))     | Just p <- isPrim v =@@ -333,8 +362,9 @@     | otherwise = case getScope v of              Hidden reason -> printMessageCheck SevError reason              Visible -> return True-             ImplUnboxed -> printMessageCheck SevWarning -                (ppr v <> text " is an external temporal function used under delay, which may cause time leaks")+             ImplUnboxed -> return True+               -- printMessageCheck SevWarning+               --  (ppr v <> text " is an external temporal function used under delay, which may cause time leaks.")   check (HsApp _ e1 e2) =     case isPrimExpr e1 of     Just (p,_) -> case p of@@ -353,16 +383,16 @@           _ -> return ch        Unbox -> check e2-      Delay -> case earlier ?ctxt of-        Just _ -> printMessageCheck SevError (text "cannot delay more than once")-        Nothing -> (\c -> c{current = Set.empty, earlier = Just (current ?ctxt)})+      Delay ->  ((\c -> c{current = Set.empty, earlier = Right (current ?ctxt)}) . stabilizeLater DelayApp)                   `modifyCtxt` check  e2       Adv -> case earlier ?ctxt of-        Just er -> mod `modifyCtxt` check e2-          where mod c =  c{earlier = Nothing, current = er,+        Right er -> mod `modifyCtxt` check e2+          where mod c =  c{earlier = Left $ TickHidden AdvApp, current = er,                            hidden = hidden ?ctxt `Map.union`                             Map.fromSet (const AdvApp) (current ?ctxt)}-        Nothing -> printMessageCheck SevError (text "can only advance under delay")+        Left NoDelay -> printMessageCheck SevError ("adv may only be used in the scope of a delay.")+        Left (TickHidden hr) -> printMessageCheck SevError ("adv may only be used in the scope of a delay. "+                            <> " There is a delay, but its scope is interrupted by " <> tickHidden hr <> ".")     _ -> liftM2 (&&) (check e1)  (check e2)   check HsUnboundVar{}  = return True   check HsConLikeOut{} = return True@@ -370,6 +400,7 @@   check HsOverLabel{} = return True   check HsIPVar{} = notSupported "implicit parameters"   check HsOverLit{} = return True+    #if __GLASGOW_HASKELL__ >= 808   check (HsAppType _ e _)@@ -385,8 +416,8 @@   check (HsWrap _ _ e) = check e   check HsLit{} = return True   check (OpApp _ e1 e2 e3) = and <$> mapM check [e1,e2,e3]-  check (HsLam _ mg) = stabilizeLater `modifyCtxt` check mg-  check (HsLamCase _ mg) = stabilizeLater `modifyCtxt` check mg+  check (HsLam _ mg) = stabilizeLater FunDef `modifyCtxt` check mg+  check (HsLamCase _ mg) = stabilizeLater FunDef `modifyCtxt` check mg   check (HsIf _ _ e1 e2 e3) = and <$> mapM check [e1,e2,e3]   check (HsCase _ e1 e2) = (&&) <$> check e1 <*> check e2   check (SectionL _ e1 e2) = (&&) <$> check e1 <*> check e2@@ -457,16 +488,13 @@ -- | This is used when checking function definitions. If the context -- is not ticked, it stays the same. Otherwise, it is stabilized -- (similar to 'box').-stabilizeLater :: Ctxt -> Ctxt-stabilizeLater c =-  if isJust (earlier c)-  then c {earlier = Nothing,-          hidden = hid,-          hiddenRec = maybe (hiddenRec c) (Map.union (hidden c) . Map.fromSet (const FunDef))-                      (fst <$> recDef c),-          recDef = Nothing}-  else c-  where hid = maybe (hidden c) (Map.union (hidden c) . Map.fromSet (const FunDef)) (earlier c)+stabilizeLater :: HiddenReason -> Ctxt -> Ctxt+stabilizeLater reason c =+  case earlier c of+    Left _ -> c+    Right earl ->+      c {earlier = Left $ TickHidden reason,+         hidden = Map.union (hidden c) $ Map.fromSet (const reason) earl}   instance Scope (ArithSeqInfo GhcTc) where@@ -526,13 +554,13 @@ -- non-recursive definition or a group of (mutual) recursive -- definitions. -checkSCC :: SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> TcM Bool-checkSCC (AcyclicSCC (b,_)) = setCtxt (emptyCtxt Nothing) (check b)+checkSCC :: ErrorMsgsRef -> SCC (LHsBindLR  GhcTc GhcTc, Set Var) -> TcM Bool+checkSCC errm (AcyclicSCC (b,_)) = setCtxt (emptyCtxt errm Nothing) (check b) -checkSCC (CyclicSCC bs) = (fmap and (mapM check' bs'))+checkSCC errm (CyclicSCC bs) = (fmap and (mapM check' bs'))   where bs' = map fst bs         vs = foldMap snd bs-        check' b@(L l _) = setCtxt (emptyCtxt (Just (vs,l))) (check b)+        check' b@(L l _) = setCtxt (emptyCtxt errm (Just (vs,l))) (check b)  -- | Stabilizes the given context, i.e. remove all non-stable types -- and any tick. This is performed on checking 'box', 'arr' and@@ -541,12 +569,10 @@ stabilize :: StableReason -> Ctxt -> Ctxt stabilize sr c = c   {current = Set.empty,-   earlier = Nothing,+   earlier = Left $ TickHidden hr,    hidden = hidden c `Map.union` Map.fromSet (const hr) ctxHid,-   hiddenRec = hiddenRec c `Map.union` maybe Map.empty (Map.fromSet (const hr) . fst) (recDef c),-   recDef = Nothing,    stabilized = Just sr}-  where ctxHid = maybe (current c) (Set.union (current c)) (earlier c)+  where ctxHid = either (const $ current c) (Set.union (current c)) (earlier c)         hr = Stabilize sr  data VarScope = Hidden SDoc | Visible | ImplUnboxed@@ -559,22 +585,15 @@     Ctxt{recDef = Just (vs,_), earlier = e}       | v `Set.member` vs ->         case e of-          Just _ -> Visible-          Nothing -> Hidden ("(Mutually) recursive call to " <> ppr v <> " must occur under delay")-    _ ->-      case Map.lookup v (hiddenRec ?ctxt) of-        Just (Stabilize (StableRec rv)) -> Hidden ("Recursive call to" <> ppr v <>-                            " is not allowed as it occurs in a local recursive definiton (at " <> ppr rv <> ")")-        Just (Stabilize StableBox) -> Hidden ("Recursive call to " <> ppr v <> " is not allowed here, since it occurs under a box")-        Just (Stabilize StableArr) -> Hidden ("Recursive call to " <> ppr v <> " is not allowed here, since it occurs inside an arrow notation")-        Just FunDef -> Hidden ("Recursive call to " <> ppr v <> " is not allowed here, since it occurs in a function that is defined under delay")-        Just AdvApp -> Hidden ("This should not happen: recursive call to " <> ppr v <> " is out of scope due to adv")-        Nothing -> -          case Map.lookup v (hidden ?ctxt) of+          Right _ -> Visible+          Left NoDelay -> Hidden ("The (mutually) recursive call to " <> ppr v <> " must occur in the scope of a delay")+          Left (TickHidden hr) -> Hidden ("The (mutually) recursive call to " <> ppr v <> " must occur in the scope of a delay. "+                            <> "There is a delay, but its scope is interrupted by " <> tickHidden hr <> ".")+    _ ->  case Map.lookup v (hidden ?ctxt) of             Just (Stabilize (StableRec rv)) ->               if (isStable (stableTypes ?ctxt) (varType v)) then Visible               else Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$-                       "It appears in a local recursive definiton (at " <> ppr rv <> ")"+                       "It appears in a local recursive definition (at " <> ppr rv <> ")"                        $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")             Just (Stabilize StableBox) ->               if (isStable (stableTypes ?ctxt) (varType v)) then Visible@@ -583,17 +602,18 @@             Just (Stabilize StableArr) ->               if (isStable (stableTypes ?ctxt) (varType v)) then Visible               else Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$-                       "It occurs under inside an arrow notation and is of type " <> ppr (varType v) <> ", which is not stable.")+                       "It occurs inside an arrow notation and is of type " <> ppr (varType v) <> ", which is not stable.")             Just AdvApp -> Hidden ("Variable " <> ppr v <> " is no longer in scope: It occurs under adv.")+            Just DelayApp -> Hidden ("Variable " <> ppr v <> " is no longer in scope due to repeated application of delay")             Just FunDef -> if (isStable (stableTypes ?ctxt) (varType v)) then Visible               else Hidden ("Variable " <> ppr v <> " is no longer in scope: It occurs in a function that is defined under a delay, is a of a non-stable type " <> ppr (varType v) <> ", and is bound outside delay")             Nothing-              | maybe False (Set.member v) (earlier ?ctxt) ->+              | either (const False) (Set.member v) (earlier ?ctxt) ->                 if isStable (stableTypes ?ctxt) (varType v) then Visible                 else Hidden ("Variable " <> ppr v <> " is no longer in scope:" $$                          "It occurs under delay" $$ "and is of type " <> ppr (varType v) <> ", which is not stable.")               | Set.member v (current ?ctxt) -> Visible-              | isTemporal (varType v) && isJust (earlier ?ctxt) && userFunction v+              | isTemporal (varType v) && isRight (earlier ?ctxt) && userFunction v                 -> ImplUnboxed               | otherwise -> Visible @@ -657,7 +677,8 @@  -- | Print a message with the current location. printMessage' :: GetCtxt => Severity -> SDoc ->  TcM ()-printMessage' sev doc = printMessage sev (srcLoc ?ctxt) doc+printMessage' sev doc =+  liftIO (modifyIORef (errorMsgs ?ctxt) ((sev ,srcLoc ?ctxt, doc) :))  -- | Print a message with the current location. Returns 'False', if -- the severity is 'SevError' and otherwise 'True.
test/IllTyped.hs view
@@ -4,9 +4,9 @@ module Main (module Main) where  import Rattus-import Rattus.Stream+import Rattus.Stream as S import Rattus.Yampa-import Prelude hiding ((<*>), map, const)+import Prelude  -- Uncomment the annotation below to check that the definitions in -- this module don't type check@@ -14,6 +14,23 @@ -- {-# ANN module Rattus #-}  ++loopIndirect :: Str Int+loopIndirect = run+  where run :: Str Int+        run = loopIndirect++        +loopIndirect' :: Str Int+loopIndirect' = let run = loopIndirect' in run+++nestedUnguard :: Str Int+nestedUnguard = run 0+  where run :: Int -> Str Int+        run 0 = nestedUnguard+        run n = n ::: delay (run (n-1))+ sfLeak :: O Int -> SF () (O Int) sfLeak  x = proc _ -> do   returnA -< x@@ -27,8 +44,8 @@ dblAdv :: O (O a) -> O a dblAdv y = delay (adv (adv y)) -dblDelay :: O (O Int)-dblDelay = delay (delay 1)+dblAdv' :: O (O a) -> O (O a)+dblAdv' y = delay (delay (adv (adv y)))  lambdaUnderDelay :: O (O Int -> Int -> Int) lambdaUnderDelay = delay (\x _ -> adv x)@@ -36,13 +53,6 @@ sneakyLambdaUnderDelay :: O (Int -> Int) sneakyLambdaUnderDelay = delay (let f _ =  adv (delay 1) in f) --lambdaUnderDelay' :: O Int -> O (Int -> O Int)-lambdaUnderDelay' x = delay (\_ -> x)--sneakyLambdaUnderDelay' :: O Int -> O (Int -> O Int)-sneakyLambdaUnderDelay' x = delay (let f _ =  x in f)- leaky :: (() -> Bool) -> Str Bool leaky p = p () ::: delay (leaky (\ _ -> hd (leaky (\ _ -> True)))) @@ -72,9 +82,6 @@  mutualLoop' :: a mutualLoop' = mutualLoop--zeros :: Box (Str Int)-zeros = box (0 ::: delay (unbox zeros))  constUnstable :: a -> Str a constUnstable a = run
test/MemoryLeak.hs view
@@ -1,19 +1,17 @@ {-# LANGUAGE TypeOperators #-}+ module Main (module Main) where  import Rattus import Rattus.Stream import Rattus.ToHaskell -import qualified Prelude-import Prelude hiding ((<*>), map) - {-# ANN module Rattus #-}  scan3 :: (Stable a) => Box(a -> a -> a) -> Box (a -> Bool) -> a -> Str a -> Str a scan3 f p acc (a ::: as) =  (if unbox p a then acc else a)-      ::: (delay (scan3 f p acc') <*> as)+      ::: (delay (scan3 f p acc') <#> as)   where acc' = unbox f acc a  
+ test/NewlyTyped.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE Arrows #-}+{-# LANGUAGE RebindableSyntax #-}++module Main (module Main) where++import Rattus+import Rattus.Stream as S+import Prelude++-- All of these examples should typecheck with the more relaxed typing+-- rules of Rattus that allows functions and delays under tick.++{-# ANN module Rattus #-}+++recBox :: Str Int+recBox = 0 ::: unbox (box (delay recBox))+++dblDelay :: O (O Int)+dblDelay = delay (delay 1)+++lambdaUnderDelay :: O (Int -> Int)+lambdaUnderDelay = delay (\x -> x)++advUnderLambda :: O (O Int -> O Int)+advUnderLambda = delay (\x -> delay (adv x))++sneakyLambdaUnderDelay :: O (Int -> Int)+sneakyLambdaUnderDelay = delay (let f x = x in f)++zeros :: Box (Str Int)+zeros = box (0 ::: delay (unbox zeros))++oneTwo :: Str Int+oneTwo = 1 ::: delay (2 ::: delay oneTwo)++data FStr a = Cons ! a ! (O (a -> O (FStr a)))++recFun :: Int -> FStr Int +recFun n = Cons n (delay (\ x -> delay (recFun x)))++nestedRec :: Str Int+nestedRec = run 10+  where run :: Int -> Str Int+        run 0 = 0 ::: delay (nestedRec)+        run n = n ::: delay (run (n-1))+++{-# ANN main NotRattus #-}+main = putStrLn "This file should type check"
test/Rewrite.hs view
@@ -3,16 +3,15 @@ module Main (module Main) where  import Rattus-import Rattus.Stream-import Prelude hiding ((<*>), map,zip,const)+import Rattus.Stream as Str  {-# ANN module Rattus #-}  twice :: Str Int -> Str Int-twice = map (box (+1)) . map (box (+1))+twice = Str.map (box (+1)) . Str.map (box (+1))  scanAndMap :: Str Int -> Str Int-scanAndMap xs = map (box (+1)) (scan (box (+)) 0 xs)+scanAndMap xs = Str.map (box (+1)) (scan (box (+)) 0 xs)  sums :: Str Int -> Str Int sums xs = scan (box (+)) 0 xs@@ -24,19 +23,19 @@ twiceScanMap xs = scan (box (+)) 0  (scanMap (box (+)) (box (+1)) 0 xs)  zipMap :: Str Int -> Str Int -> Str Int-zipMap xs ys = map (box (\ (x:*y) -> x + y)) (zip xs ys)+zipMap xs ys = Str.map (box (\ (x:*y) -> x + y)) (Str.zip xs ys)  constMap :: Str Int-constMap = map (box (+1)) (const 5)+constMap = Str.map (box (+1)) (Str.const 5)    apply :: O (Int -> Int -> Int) -> O Int -> O Int -> O Int-apply f x y = f <*> x <*> y+apply f x y = f <#> x <#> y   apply' :: O (Int -> Int -> Int) -> Int -> O Int -> O Int-apply' f x y = f <** x <*> y+apply' f x y = f <## x <#> y   {-# ANN main NotRattus #-}
test/TimeLeak.hs view
@@ -1,13 +1,11 @@ {-# LANGUAGE TypeOperators #-}+ module Main (module Main) where  import Rattus-import Rattus.Stream+import Rattus.Stream as Str import Rattus.ToHaskell -import Prelude hiding ((<*>), map)-- {-# ANN module Rattus #-}  @@ -23,10 +21,10 @@  -- This function should cause a warning. leakyNats :: Str Int-leakyNats = 0 ::: delay (map (box (+1)) leakyNats)+leakyNats = 0 ::: delay (Str.map (box (+1)) leakyNats)  inc :: Str Int -> Str Int-inc = map (box ((+)1))+inc = Str.map (box ((+)1))  -- This function should cause a warning. @@ -45,7 +43,7 @@  -- This function should cause a warning. mapMap :: Box (a -> a) -> Box (a -> a) -> Str a -> Str a-mapMap f g (x ::: xs) = unbox f x ::: delay (map g (mapMap g f (adv xs)))+mapMap f g (x ::: xs) = unbox f x ::: delay (Str.map g (mapMap g f (adv xs)))  -- This function should cause a warning. leakyMap :: Str Int@@ -68,11 +66,11 @@  -- This function should cause a warning. natsTrans :: Str Int -> Str Int-natsTrans (x ::: xs) = x ::: delay (map (box ((+)x)) $ natsTrans $ adv xs)+natsTrans (x ::: xs) = x ::: delay (Str.map (box ((+)x)) $ natsTrans $ adv xs)  -- This function should cause a warning. leakySum :: Box (Int -> Int) -> Str Int -> Str Int-leakySum f (x ::: xs) = unbox f x ::: (delay (leakySum (box (\ y -> unbox f (y + x)))) <*> xs)+leakySum f (x ::: xs) = unbox f x ::: (delay (leakySum (box (\ y -> unbox f (y + x)))) <#> xs)   {-# ANN recurse NotRattus #-}
test/WellTyped.hs view
@@ -7,9 +7,8 @@ import Rattus import Rattus.Stream import Rattus.Yampa-import Prelude hiding ((<*>))-import Data.Set-import qualified Data.Set as Set+import Data.Set as Set+import Prelude   {-# ANN module Rattus #-}@@ -56,40 +55,40 @@ map1 f (x ::: xs) = unbox f x ::: delay (map1 f (adv xs))  map2 :: Box (a -> b) -> Str a -> Str b-map2 f (x ::: xs) = unbox f x ::: (delay map2 <** f <*> xs)+map2 f (x ::: xs) = unbox f x ::: (delay map2 <## f <#> xs)  map3 :: Box (a -> b) -> Str a -> Str b map3 f = run-  where run (x ::: xs) = unbox f x ::: (delay run <*> xs)+  where run (x ::: xs) = unbox f x ::: (delay run <#> xs)   -- local mutual recursive definition nestedMutual :: Str Int -> Str Int nestedMutual = lbar1 (box (+1))   where lbar1 :: Box (a -> b) -> Str a -> Str b-        lbar1 f (x ::: xs) = unbox f x ::: (delay (lbar2 f) <*> xs)+        lbar1 f (x ::: xs) = unbox f x ::: (delay (lbar2 f) <#> xs)          lbar2 :: Box (a -> b) -> Str a -> Str b-        lbar2 f  (x ::: xs) = unbox f x ::: (delay (lbar1 f) <*> xs)+        lbar2 f  (x ::: xs) = unbox f x ::: (delay (lbar1 f) <#> xs)    -- mutual recursive definition bar1 :: Box (a -> b) -> Str a -> Str b-bar1 f (x ::: xs) = unbox f x ::: (delay (bar2 f) <*> xs)+bar1 f (x ::: xs) = unbox f x ::: (delay (bar2 f) <#> xs)  bar2 :: Box (a -> b) -> Str a -> Str b-bar2 f  (x ::: xs) = unbox f x ::: (delay (bar1 f) <*> xs)+bar2 f  (x ::: xs) = unbox f x ::: (delay (bar1 f) <#> xs)   -- mutual recursive definition foo1,foo2 :: Box (a -> b) -> Str a -> Str b-(foo1,foo2) = (\ f (x ::: xs) -> unbox f x ::: (delay (foo2 f) <*> xs),-               \ f (x ::: xs) -> unbox f x ::: (delay (foo1 f) <*> xs))+(foo1,foo2) = (\ f (x ::: xs) -> unbox f x ::: (delay (foo2 f) <#> xs),+               \ f (x ::: xs) -> unbox f x ::: (delay (foo1 f) <#> xs))   applyDelay :: O (O (a -> b)) -> O (O a) -> O (O b)-applyDelay f x = delay (adv f <*> adv x)+applyDelay f x = delay (adv f <#> adv x)   stableDelay :: Stable a => a -> O a@@ -145,6 +144,14 @@  alt :: Int -> Int -> Str Int alt n m = n ::: delay (alt m n)+++myMap :: Str Int -> Str Int+myMap (x ::: xs) = (x + 1) ::: delay (fst' (myMap (adv xs):*nats))++nats :: Str Int+nats = 0 ::: delay (myMap nats)+   {-# ANN main NotRattus #-}