packages feed

explicit-sharing 0.5.1.2 → 0.6

raw patch · 4 files changed

+489/−7 lines, 4 filesdep +derivedep +template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: derive, template-haskell

API changes (from Hackage documentation)

+ Control.Monad.Sharing.Classes: instance (Monad m) => Shareable m (a -> b)
+ Control.Monad.Sharing.Classes: type MBool m = Bool
+ Control.Monad.Sharing.Classes: type MChar m = Char
+ Control.Monad.Sharing.Classes: type MInt m = Int
+ Data.Monadic.Derive: makeConvertible :: Derivation
+ Data.Monadic.Derive: makeMData :: Derivation
+ Data.Monadic.Derive: makeShareable :: Derivation
+ Data.Monadic.Derive: monadic :: Derivation

Files

Control/Monad/Sharing/Classes.hs view
@@ -19,8 +19,10 @@ -- sharing. module Control.Monad.Sharing.Classes ( -  Sharing(..), Shareable(..), Convertible(..), convert+  Sharing(..), Shareable(..), Convertible(..), convert, +  MInt, MChar, MBool+  ) where  -- | Interface of monads that support explicit sharing.@@ -44,9 +46,13 @@ -- could be applied. class Shareable m a  where-  shareArgs :: Monad n -            => (forall b . Shareable m b => m b -> n (m b)) -> a -> n a+  shareArgs :: Monad n => +               (forall b . Shareable m b => m b -> n (m b)) -> a -> n a +type MInt  m = Int+type MChar m = Char+type MBool m = Bool+ instance Monad m => Shareable m Bool  where   shareArgs _ = return@@ -68,6 +74,10 @@   shareArgs _ = return  instance Monad m => Shareable m [Char]+ where+  shareArgs _ = return++instance Monad m => Shareable m (a -> b)  where   shareArgs _ = return 
Control/Monad/Sharing/Implementation/CPS.hs view
@@ -104,7 +104,7 @@ -- 'Lazy' is a monad transformer. instance MonadTrans Lazy  where-  lift a = Lazy (\c s -> a >>= \x -> c x s)+  lift a = Lazy (\c s -> a >>= flip c s)  -- If the underlying monad supports IO we can lift this functionality. instance MonadIO m => MonadIO (Lazy m)
+ Data/Monadic/Derive.hs view
@@ -0,0 +1,469 @@+-- | +-- Module      : Data.Monadic.Derive+-- Copyright   : Sebastian Fischer+-- License     : PublicDomain+-- Maintainer  : Sebastian Fischer <mailto:sebf@informatik.uni-kiel.de>+-- Stability   : experimental+-- +-- Automatic deriving of monadic data types and corresponding instances.+module Data.Monadic.Derive (++  monadic, makeMData, makeShareable, makeConvertible++  ) where++import Language.Haskell+import Data.Derive.Internal.Derivation++import Control.Monad.Error+import Control.Applicative+import Control.Arrow++typeParamName, branchResName, funArgName :: String+typeParamName = "m"; branchResName = "a"; funArgName = "fun"++-- | Derives monadic datatypes and instances for explicit sharing as+--   well as conversion. Combines the other three derivations which+--   provide the same functionality split into different parts.+-- +--   You usually need the following preamble when deriving monadic code:+-- +-- > {-# LANGUAGE TemplateHaskell+-- >   , KindSignatures+-- >   , MultiParamTypeClasses+-- >   , FlexibleInstances+-- >   #-}+-- > import Control.Monad.Sharing+-- > import Data.Monadic.Derive+-- > import Data.DeriveTH+-- +--   If your types contain lists, you also need to+-- +-- > import Data.Monadic.List+-- +-- With this prerequisites, you can derive a monadic 'Maybe' type by+-- +-- > $(derive monadic ''Maybe)+-- +monadic :: Derivation+monadic = derivationCustom "Monadic"+            (\ (_,d) -> concat <$> mapM ($d) [convData,shareableInst,convInsts])++-- | Generates a monadic datatype and corresponding con- and+--   destructor functions from a Haskell datatype.+-- +--   For example, the datatype+-- +-- > data Maybe a = Nothing | Just a+-- +--   can be translated into its monadic counterpart by typing+-- +-- > $(derive makeMData ''Maybe)+-- +--   This call generates the following datatype+-- +-- > data MMaybe m a = MNothing | MJust (m a)+-- +--   and the following auxiliary functions for constructing and+--   matching monadic values:+-- +-- > mNothing :: Monad m => m (MMaybe m a)+-- > mNothing = return MNothing+-- +-- > mJust :: Monad m => m a -> m (MMaybe m a)+-- > mJust a = return (MJust a)+-- +-- > matchMMaybe :: Monad m => m (MMaybe m a) -> m b -> (m a -> m b) -> m b+-- > matchMMaybe x n j = x >>= \x -> case x of { MNothing -> n; MJust a -> j a }+-- +makeMData :: Derivation+makeMData = derivationCustom "MData" (convData . snd)++-- | Generates a 'Shareable' instance for a monadic datatype.+-- +--   For example the call+-- +-- > $(derive makeShareable ''Maybe)+-- +--   generates the following instance:+-- +-- > instance (Monad m, Shareable m a) => Shareable (Maybe m a) where+-- >   shareArgs fun MNothing  = return MNothing+-- >   shareArgs fun (MJust a) = fun a >>= \a -> mJust a+-- +makeShareable :: Derivation+makeShareable = derivationCustom "Shareable" (shareableInst . snd)++-- | Generates 'Convertible' instances to convert between monadic and+--   non-monadic datatypes.+-- +--   For example, the call+-- +-- > $(derive makeConvertible ''Maybe)+-- +--   generates the following instances:+-- +-- > instance (Monad m, Convertible m a a')+-- >       => Convertible m (Maybe a) (MMaybe m a') where+-- >   convArgs fun Nothing  = mNothing+-- >   convArgs fun (Just a) = mJust (fun a)+-- > +-- > instance (Monad m, Convertible m a' a)+-- >       => Convertible m (MMaybe m a') (Maybe a) where+-- >   convArgs fun MNothing  = return Nothing+-- >   convArgs fun (MJust a) = (a >>= fun) >>= \a -> return (Just a)+-- +makeConvertible :: Derivation+makeConvertible = derivationCustom "Convertible" (convInsts . snd)++-- printDecls (Left s) = Left s+-- printDecls (Right ds) = trace (unlines . map prettyPrint $ ds) (Right ds)++type Conv a = Either String a++convData :: Decl -> Conv [Decl]+convData (DataDecl _ dataOrNew ctx name args cs _) = +  do cs' <- mapM convQCons cs+     let decl = DataDecl sl dataOrNew ctx (convName True name) (m:args) cs' []+     cfuns <- concat <$> mapM (makeCFunT name args) cs+     mfun <- makeMatchFunT name args cs+     return (decl:cfuns++mfun)+ where m = KindedVar (Ident typeParamName) (KindStar `KindFn` KindStar)++convData _ = fail "Data.Monadic.Derive: no data declaration"++-- Derive does not create Symbols.+-- Hence, we cannot rely on: Ident => prefix, Symbol => infix+convName :: Bool -> Name -> Name+convName isCons name | all isSymbolChar s && isCons = Symbol (s++"~")+                     | all isSymbolChar s           = Symbol ('~':s)+                     | isCons                       = Ident  ('M':s)+                     | otherwise                    = Ident  ('m':s)+ where s = fromName name++convQCons :: QualConDecl -> Conv QualConDecl+convQCons (QualConDecl sl vs ctx con) = QualConDecl sl vs ctx <$> convCons con++convCons :: ConDecl -> Conv ConDecl++convCons (ConDecl name args) =+  ConDecl (convName True name) <$> mapM convBType args++convCons (InfixConDecl l name r) =+  do [l',r'] <- mapM convBType [l,r]+     return $ InfixConDecl l' (convName True name) r'++convCons (RecDecl name fields) =+  RecDecl (convName True name) <$> mapM convField fields+ where convField (ns,bt) = do bt' <- convBType bt+                              return (map (convName False) ns, bt')++convBType :: BangType -> Conv BangType+convBType (BangedTy   t) = BangedTy <$> convType t+convBType (UnpackedTy t) = UnpackedTy <$> convType t+convBType (UnBangedTy t) = UnBangedTy . TyApp m <$> convType t+ where m = TyVar (Ident typeParamName)++convType :: Type -> Conv Type+convType (TyVar name) = return $ TyVar name+convType (TyParen t) = TyParen <$> convType t+convType (TyApp f x) = liftM2 TyApp (convType f) (convType x)+convType (TyCon (UnQual name)) =+  return $ TyApp (TyCon (UnQual (convName True name))) m+ where m = TyVar (Ident typeParamName)+convType (TyCon (Special ListCon)) =+  return $ TyApp (TyCon (UnQual (Ident "List"))) m+ where m = TyVar (Ident typeParamName)+convType (TyFun a b) =+  liftM2 TyFun (fromBangType <$> convBType (UnBangedTy a))+               (fromBangType <$> convBType (UnBangedTy b))++convType t = fail $ "Data.Monadic.Derive: unsupported type " ++ show t++makeCFunT :: Name -> [TyVarBind] -> QualConDecl -> Conv [Decl]+makeCFunT tname targs (QualConDecl _ _ ctx con) =+  do argts <- mapM (convBType . UnBangedTy . fromBangType) (consArgs con)+     let typ = TyForall Nothing (ClassA (UnQual (Ident "Monad")) [m]:ctx) $+                 foldr (TyFun . fromBangType) (makeType tname targs) argts+     return [TypeSig sl [convName False (consName con)] typ,+             makeCFun (consName con) (consArgs con)]+ where m = TyVar (Ident typeParamName)++makeType :: Name -> [TyVarBind] -> Type+makeType name args =+  TyApp m (foldl TyApp (TyCon (UnQual (convName True name)))+                       (m:map tVar args))+ where m = TyVar (Ident typeParamName)++makeCFun :: Name -> [BangType] -> Decl+makeCFun name [] =+  PatBind sl (PVar (convName False name))+    Nothing (UnGuardedRhs rhs) (BDecls [])+ where+  rhs = App (Var (UnQual (Ident "return"))) $ Con (UnQual (convName True name))++makeCFun name argts =+  FunBind [Match sl (convName False name) (map PVar argvs)+    Nothing (UnGuardedRhs rhs) (BDecls [])]+ where+  argvs = take (length argts) $ map (Ident . (:[])) ['a'..]+  rhs   = foldr bind (App (Var (UnQual (Ident "return")))+                          (foldl App (Con (UnQual (convName True name)))+                                     (map (Var . UnQual) argvs)))+                     (map fst . filter (isBangType . snd) $ zip argvs argts)+  bind a b = InfixApp (Var (UnQual a)) (QVarOp (UnQual (Symbol ">>=")))+                      (Lambda sl [PVar a] b)++makeMatchFunT :: Name -> [TyVarBind] -> [QualConDecl] -> Conv [Decl]+makeMatchFunT (Symbol _) _ _ = return []+makeMatchFunT tname@(Ident s) targs cs =+  do ts <- mapM branchTypeC cs+     let typ = TyForall Nothing [ClassA (UnQual (Ident "Monad")) [m]] $+                 foldr TyFun (TyApp m a) (makeType tname targs:ts)+     return [TypeSig sl [name] typ,+             makeMatchFun name (map conDecl cs)]+ where+  m = TyVar (Ident typeParamName)+  a = TyVar (Ident branchResName)+  name = Ident $ "matchM" ++ s++branchTypeC :: QualConDecl -> Conv Type+branchTypeC (QualConDecl _ _ ctx con) =+  TyForall Nothing ctx <$> branchType (consArgs con)++branchType :: [BangType] -> Conv Type+branchType ts =+  foldr (TyFun . fromBangType) (TyApp m a) <$>+    mapM (convBType . UnBangedTy . fromBangType) ts+ where m = TyVar (Ident typeParamName)+       a = TyVar (Ident branchResName)++makeMatchFun :: Name -> [ConDecl] -> Decl+makeMatchFun name cs =+  FunBind [Match sl name (map PVar args) Nothing (UnGuardedRhs rhs) (BDecls [])]+ where+  args = take (1+length cs) . map (Ident . (:[])) $ ['a'..]+  var = head args+  rhs = InfixApp (Var (UnQual var))+                 (QVarOp (UnQual (Symbol ">>=")))+                 (Lambda sl [PVar var] $+                    Case (Var (UnQual var)) (zipWith makeAlt cs (tail args)))++makeAlt :: ConDecl -> Name -> Alt+makeAlt con fun =+  Alt sl (PApp (UnQual name) (map PVar args)) (UnGuardedAlt rhs) (BDecls [])+ where+  name = convName True (consName con)+  args = map Ident . zipWith (const (:"'")) (consArgs con) $ ['a'..]++  rhs = foldl App (Var (UnQual fun))+      . zipWith arg (consArgs con)+      $ map (Var . UnQual) args++  arg t x | isBangType t = App (Var (UnQual (Ident "return"))) x+          | otherwise    = x++shareableInst :: Decl -> Conv [Decl]+shareableInst (DataDecl _ _ _ name args cs _) =+  do rules <- mapM makeShareArgsRule cs+     return [InstDecl sl ctx (UnQual (Ident "Shareable")) [m,t] $+               [InsDecl $ FunBind rules]]+ where+  m   = TyVar (Ident typeParamName)+  t   = foldl TyApp (TyCon (UnQual (convName True name))) (m:map tVar args)+  ctx = ClassA (UnQual (Ident "Monad")) [m]+        : map (\a -> ClassA (UnQual (Ident "Shareable")) [m,tVar a]) args++shareableInst d = fail $ "Cannot make Shareable instance for " ++ show d++makeShareArgsRule :: QualConDecl -> Conv Match+makeShareArgsRule (QualConDecl _ [] [] con) =+  return $ Match sl (Ident "shareArgs") [PVar fun,cpat] Nothing +             (UnGuardedRhs rhs) (BDecls [])+ where+  name = convName True $ consName con+  args = map (Ident.(:[]).fst) . zip ['a'..] $ consArgs con++  fun  = Ident funArgName+  cpat = UnQual name `PApp` map PVar args+  cexp = foldl App (Con (UnQual name)) $ map (Var . UnQual) args++  rhs  = foldr (\ (x,b) e ->+                 InfixApp (if b then+                             Var (UnQual (Ident "shareArgs"))+                              `App` Var (UnQual fun)+                              `App` Var (UnQual x)+                            else Var (UnQual fun) `App` Var (UnQual x))+                          (QVarOp (UnQual (Symbol ">>=")))+                          (Lambda sl [PVar x] e))+           (Var (UnQual (Ident "return")) `App` cexp)+           (zipWith (curry $ second isBangType) args (consArgs con))++makeShareArgsRule c = fail $ "Cannot make shareArgs rule for " ++ show c++convInsts :: Decl -> Conv [Decl]+convInsts (DataDecl _ _ _ name args cs _) =+  do rules  <- mapM makeConvToM cs+     rules' <- mapM makeConvFromM cs+     return [InstDecl sl (mctx:zipWith convCtx (map tVar args) args')+               cname [m,t,t'] [InsDecl $ FunBind rules],+             InstDecl sl (mctx:zipWith convCtx args' (map tVar args))+               cname [m,t',t] [InsDecl $ FunBind rules']]+ where+  m     = TyVar $ Ident typeParamName+  cname = UnQual $ Ident "Convertible"+  mctx  = ClassA (UnQual (Ident "Monad")) [m]+  args' = map (TyVar . Ident . (:[]) . fst) $ zip ['a'..] args+  t     = foldl TyApp (TyCon (UnQual name)) (map tVar args)+  t'    = foldl TyApp (TyCon (UnQual (convName True name))) (m:args')++  convCtx a b = ClassA cname [m,a,b]++convInsts d = fail $ "Cannot make Convertible instances for " ++ show d++makeConvToM :: QualConDecl -> Conv Match+makeConvToM (QualConDecl _ [] [] con) =+  return $ Match sl (Ident "convArgs") [PVar fun,cpat] Nothing+             (UnGuardedRhs rhs) (BDecls [])+ where+  name = consName con+  args = map (Ident.(:[]).fst) . zip ['a'..] $ consArgs con++  fun  = Ident funArgName+  cpat = UnQual name `PApp` map PVar args++  rhs  = foldl App (Var (UnQual (convName False name))) $+           map (\x -> Var (UnQual fun) `App` Var (UnQual x)) args++makeConvToM c = fail $ "Cannot make convArgs rule for " ++ show c++makeConvFromM :: QualConDecl -> Conv Match+makeConvFromM (QualConDecl _ [] [] con) =+  return $ Match sl (Ident "convArgs") [PVar fun,cpat] Nothing+             (UnGuardedRhs rhs) (BDecls [])+ where+  name = consName con+  args = map (Ident.(:[]).fst) . zip ['a'..] $ consArgs con++  fun  = Ident funArgName+  cpat = UnQual (convName True name) `PApp` map PVar args+  cexp = foldl App (Con (UnQual name)) $ map (Var . UnQual) args++  rhs  = foldr (\ (x,b) e ->+                  InfixApp+                    (if b then Var (UnQual fun) `App` Var (UnQual x)+                      else Paren $ InfixApp+                             (Var (UnQual x))+                             (QVarOp (UnQual (Symbol ">>=")))+                             (Var (UnQual fun)))+                    (QVarOp (UnQual (Symbol ">>=")))+                    (Lambda sl [PVar x] e))+           (Var (UnQual (Ident "return")) `App` cexp)+           (zipWith (curry $ second isBangType) args (consArgs con))++makeConvFromM c = fail $ "Cannot make convArgs rule for " ++ show c++fromName :: Name -> String+fromName (Ident  name) = name+fromName (Symbol name) = name++-- does not recognise unicode symbols+isSymbolChar :: Char -> Bool+isSymbolChar c = c `elem` ":'!#$%&*+./<=>?@\\^|_~"++consName :: ConDecl -> Name+consName (ConDecl name _)        = name+consName (InfixConDecl _ name _) = name+consName (RecDecl name _)        = name++consArgs :: ConDecl -> [BangType]+consArgs (ConDecl _ args)     = args+consArgs (InfixConDecl l _ r) = [l,r]+consArgs (RecDecl _ fs)       = [t | (ns,t) <- fs, _ <- ns]++tVar :: TyVarBind -> Type+tVar (UnkindedVar name) = TyVar name+tVar (KindedVar name kind) = TyKind (TyVar name) kind++isBangType :: BangType -> Bool+isBangType (UnBangedTy _) = False+isBangType _              = True++conDecl :: QualConDecl -> ConDecl+conDecl (QualConDecl _ _ _ con) = con++{- example derivations++data  List               a =  Nil |  Cons    a      (List   a)+data MList (m :: * -> *) a = MNil | MCons (m a) (m (MList m a))++mNil :: Monad m => m (MList m a)+mNil = return MNil++mCons :: Monad m => m a -> m (MList m a) -> m (MList m a)+mCons x xs = return (MCons x xs)++matchMList :: Monad m+           => m (MList m a)+           -> m b -> (m a -> m (MList m a) -> m b)+           -> m b+matchMList list nil cons =+  list >>= \list -> +  case list of+    MNil       -> nil+    MCons x xs -> cons x xs++instance (Monad m, Shareable m a) => Shareable m (List m a)+ where+  shareArgs f MNil = return MNil+  shareArgs f (MCons x xs) =+    f x >>= \x -> f xs >>= \xs -> return (MCons x xs)++instance (Monad m, Convertible m a a') => Convertible m (List a) (MList m a')+ where+  convArgs f Nil = mNil+  convArgs f (Cons x xs) = mCons (f x) (f xs)++instance (Monad m, Convertible m a a') => Convertible m (MList m a) (List a')+ where+  convArgs f MNil = return Nil+  convArgs f (MCons x xs) =+    (x >>= f) >>= \x -> (xs >>= f) >>= \xs -> return (Cons x xs)++data  SList               a =  SNil |  SCons !a     (SList   a)+data MSList (m :: * -> *) a = MSNil | MSCons !a (m (MSList m a))++mSNil :: Monad m => m (MSList m a)+mSNil = return MSNil++mSCons :: Monad m => m a -> m (MSList m a) -> m (MSList m a)+mSCons x xs = x >>= \x -> return (MSCons x xs)++matchMSList :: Monad m+            => m (MSList m a)+            -> m b -> (m a -> m (MSList m a) -> m b)+            -> m b+matchMSList list nil cons =+  list >>= \list -> +  case list of+    MSNil       -> nil+    MSCons x xs -> cons (return x) xs++instance (Monad m, Shareable m a) => Shareable m (MSList m a)+ where+  shareArgs f MSNil = return MSNil+  shareArgs f (MSCons x xs) =+    shareArgs f x >>= \x -> f xs >>= \xs -> return (MSCons x xs)++instance (Monad m, Convertible m a a') => Convertible m (SList a) (MSList m a')+ where+  convArgs f SNil = mSNil+  convArgs f (SCons x xs) = mSCons (f x) (f xs)++instance (Monad m, Convertible m a a') => Convertible m (MSList m a) (SList a')+ where+  convArgs f MSNil = return SNil+  convArgs f (MSCons x xs) =+    f x >>= \x -> (xs >>= f) >>= \xs -> return (Cons x xs)++-}
explicit-sharing.cabal view
@@ -1,5 +1,5 @@ Name:          explicit-sharing-Version:       0.5.1.2+Version:       0.6 Cabal-Version: >= 1.6 Synopsis:      Explicit Sharing of Monadic Effects Description:   @@ -20,14 +20,17 @@ Extra-Source-Files: Test.hs  Library-  Build-Depends:    base >= 3 && < 5, containers, mtl+  Build-Depends:    base >= 3 && < 5, containers, mtl,+                    template-haskell >= 2.4 && < 2.5,+                    derive >= 2.3 && < 2.4   Exposed-Modules:  Control.Monad.Sharing,                     Control.Monad.Sharing.Classes,                     Control.Monad.Sharing.FirstOrder,+                    Data.Monadic.Derive,                     Data.Monadic.List   Other-Modules:    Control.Monad.Sharing.Implementation.CPS,                     Control.Monad.Sharing.Implementation.FirstOrder-  Ghc-Options:      -Wall+  Ghc-Options:      -Wall -fno-warn-name-shadowing   Extensions:       ExistentialQuantification,                     MultiParamTypeClasses,                     FlexibleInstances,