packages feed

compstrat (empty) → 0.1.0.0

raw patch · 7 files changed

+461/−0 lines, 7 filesdep +basedep +compdatadep +mtlsetup-changed

Dependencies added: base, compdata, mtl, template-haskell, th-expand-syns, transformers

Files

+ Data/Comp/Multi/Strategic.hs view
@@ -0,0 +1,213 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}++module Data.Comp.Multi.Strategic+  (+    -- * Rewrites+    RewriteM+  , Rewrite+  , GRewriteM+  , GRewrite+  , addFail+  , tryR+  , promoteR+  , promoteRF+  , allR+  , (>+>)+  , (+>)+  , anyR+  , oneR+  , alltdR+  , allbuR+  , anytdR+  , anybuR+  , prunetdR+  , onetdR+  , onebuR++    -- * Translations+  , Translate+  , TranslateM+  , GTranslateM+  , promoteTF+  , mtryM+  , onetdT+  , foldtdT+  , crushtdT+  ) where++import Control.Applicative ( Applicative, (<*) )++import Control.Monad ( MonadPlus(..), liftM, liftM2, (>=>) )+import Control.Monad.Identity ( Identity )+import Control.Monad.Trans ( lift )+import Control.Monad.Trans.Maybe ( MaybeT, runMaybeT )+import Control.Monad.State ( StateT, runStateT, get, put )+import Control.Monad.Writer ( WriterT, runWriterT, tell )++import Data.Comp.Multi ( Cxt(..), Term, unTerm )+import Data.Comp.Multi.Generic ( query )+import Data.Comp.Multi.HFoldable ( HFoldable )+import Data.Comp.Multi.HTraversable ( HTraversable, hmapM )+import Data.Monoid ( Monoid, mappend, mempty, Any(..) )+import Data.Type.Equality ( (:~:)(..), sym )++import Data.Comp.Multi.Strategy.Classification++--------------------------------------------------------------------------------++-- Porting from the old type-equality library to the new base Data.Type.Equality+-- Haven't yet looked into rewriting with gcastWith instead++subst :: (a :~: b) -> f a -> f b+subst Refl x = x++subst2 :: (a :~: b) -> f (g a) -> f (g b)+subst2 Refl x = x++--------------------------------------------------------------------------------++type RewriteM m f l = f l -> m (f l)+type Rewrite f l = RewriteM Identity f l+type GRewriteM m f = forall l. RewriteM m f l+type GRewrite f = GRewriteM Identity f++--------------------------------------------------------------------------------+-- Rewrites+--------------------------------------------------------------------------------++type AnyR m = WriterT Any m++wrapAnyR :: (Applicative m, MonadPlus m) => RewriteM m f l -> RewriteM (AnyR m) f l+wrapAnyR f t = (lift (f t) <* tell (Any True)) `mplus` return t++unwrapAnyR :: MonadPlus m => RewriteM (AnyR m) f l -> RewriteM m f l+unwrapAnyR f t = do (t', Any b) <- runWriterT (f t)+                    if b then+                      return t'+                     else+                      mzero++--------------------------------------------------------------------------------++type OneR m = StateT Bool m++wrapOneR :: (Applicative m, MonadPlus m) => RewriteM m f l -> RewriteM (OneR m) f l+wrapOneR f t = do b <- get+                  if b then+                    return t+                   else+                    (lift (f t) <* put True) `mplus` return t++unwrapOneR :: MonadPlus m => RewriteM (OneR m) f l -> RewriteM m f l+unwrapOneR f t = do (t', b) <- runStateT (f t) False+                    if b then+                      return t'+                     else+                      mzero++--------------------------------------------------------------------------------++dynamicR :: (DynCase f l, MonadPlus m) => RewriteM m f l -> GRewriteM m f+dynamicR f t = case dyncase t of+                 Just p -> subst2 (sym p) $ f (subst p t)+                 Nothing -> mzero++tryR :: (Monad m) => RewriteM (MaybeT m) f l -> RewriteM m f l+tryR f t = liftM (maybe t id) $ runMaybeT (f t)++promoteR :: (DynCase f l, Monad m) => RewriteM (MaybeT m) f l -> GRewriteM m f+promoteR = tryR . dynamicR++promoteRF :: (DynCase f l, Monad m) => RewriteM (MaybeT m) f l -> GRewriteM (MaybeT m) f+promoteRF = dynamicR++-- | Applies a rewrite to all immediate subterms of the current term+allR :: (Monad m, HTraversable f) => GRewriteM m (Term f) -> RewriteM m (Term f) l+allR f t = liftM Term $ hmapM f $ unTerm t++-- | Applies two rewrites in suceesion, succeeding if one or both succeed+(>+>) :: (Applicative m, MonadPlus m) => GRewriteM m f -> GRewriteM m f -> GRewriteM m f+f >+> g = unwrapAnyR (wrapAnyR f >=> wrapAnyR g)++-- | Left-biased choice -- (f +> g) runs f, and, if it fails, then runs g+(+>) :: (MonadPlus m) => RewriteM m f l -> RewriteM m f l -> RewriteM m f l+(+>) f g x = f x `mplus` g x++-- | Applies a rewrite to all immediate subterms of the current term, succeeding if any succeed+anyR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> RewriteM m (Term f) l+anyR f = unwrapAnyR $ allR $ wrapAnyR f -- not point-free because of type inference++-- | Applies a rewrite to the first immediate subterm of the current term where it can succeed+oneR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> RewriteM m (Term f) l+oneR f = unwrapOneR $ allR $ wrapOneR f -- not point-free because of type inference++-- | Runs a rewrite in a bottom-up traversal+allbuR :: (Monad m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+allbuR f = allR (allbuR f) >=> f++-- | Runs a rewrite in a top-down traversal+alltdR :: (Monad m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+alltdR f = f >=> allR (alltdR f)++-- | Runs a rewrite in a bottom-up traversal, succeeding if any succeed+anybuR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+anybuR f = anyR (anybuR f) >+> f++-- | Runs a rewrite in a top-down traversal, succeeding if any succeed+anytdR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+anytdR f = f >+> anyR (anytdR f)++-- | Runs a rewrite in a top-down traversal, succeeding if any succeed, and pruning below successes+prunetdR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+prunetdR f = f +> anyR (prunetdR f)++-- | Applies a rewrite to the first node where it can succeed in a bottom-up traversal+onebuR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+onebuR f = oneR (onebuR f) +> f++-- | Applies a rewrite to the first node where it can succeed in a top-down traversal+onetdR :: (Applicative m, MonadPlus m, HTraversable f) => GRewriteM m (Term f) -> GRewriteM m (Term f)+onetdR f = f +> oneR (onetdR f)++--------------------------------------------------------------------------------+-- Translations+--------------------------------------------------------------------------------++-- | A single-sorted translation in the Identity monad+type Translate f l t = TranslateM Identity f l t++-- | A monadic translation for a single sort+type TranslateM m f l t = f l -> m t++-- | A monadic translation for all sorts+type GTranslateM m f t = forall l. TranslateM m f l t++-- | Allows a one-sorted translation to be applied to any sort, failing at sorts+--   different form the original+promoteTF :: (DynCase f l, MonadPlus m) => TranslateM m f l t -> GTranslateM m f t+promoteTF f t = case dyncase t of+                  Just p -> f (subst p t)+                  Nothing -> mzero++-- | Lifts a translation into the Maybe monad, allowing it to fail+addFail :: Monad m => TranslateM m f l t -> TranslateM (MaybeT m) f l t+addFail = (lift . )++-- | Runs a failable computation, replacing failure with mempty+mtryM :: (Monad m, Monoid a) => MaybeT m a -> m a+mtryM = liftM (maybe mempty id) . runMaybeT++-- | Runs a translation in a top-down manner, combining its+--   When run using MaybeT, returns its result for the last node where it succeded+onetdT :: (MonadPlus m, HFoldable f) => GTranslateM m (Term f) t -> GTranslateM m (Term f) t+onetdT t = query t mplus++-- | Fold a tree in a top-down manner+foldtdT :: (HFoldable f, Monoid t, Monad m) => GTranslateM m (Term f) t -> GTranslateM m (Term f) t+foldtdT t = query t (liftM2 mappend)++-- | An always successful top-down fold, replacing failures with mempty.+crushtdT :: (HFoldable f, Monoid t, Monad m) => GTranslateM (MaybeT m) (Term f) t -> GTranslateM m (Term f) t+crushtdT f = foldtdT $ mtryM . f
+ Data/Comp/Multi/Strategy/Classification.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- | +-- +-- This module contains typeclasses and operations allowing dynamic casing on sorts.++module Data.Comp.Multi.Strategy.Classification+  (+    DynCase(..)+  , KDynCase(..)+  , dynProj+  , caseE+  ) where++import Data.Comp.Multi ( (:+:), E, K, runE, caseH, (:&:), remA, Cxt(..) )+import Data.Type.Equality ( (:~:)(..), gcastWith )++--------------------------------------------------------------------------------+++-- |+-- This operation allows you to rediscover the label giving+-- the sort of a term by inspecting the term. It is mainly used+-- through the 'caseE' and 'dynProj' operators+class DynCase f a where+  -- | Determine whether a node has sort @a@+  dyncase :: f b -> Maybe (b :~: a)++-- | An instance @KDynCase f a@ defines an instance @DynCase (Term f) a@+class KDynCase f a where+  kdyncase :: forall (e :: * -> *) b. DynCase e a => f e b -> Maybe (b :~: a)++instance KDynCase f a where+  kdyncase = const Nothing++instance (KDynCase f l, KDynCase g l) => KDynCase (f :+: g) l where+  kdyncase = caseH kdyncase kdyncase++instance DynCase (K a) b where+  dyncase _ = Nothing++instance (KDynCase f l, DynCase a l) => DynCase (Cxt h f a) l where+  dyncase (Term x) = kdyncase x+  dyncase (Hole x) = dyncase x++instance (KDynCase f l) => KDynCase (f :&: a) l where+  kdyncase = kdyncase . remA++--------------------------------------------------------------------------------++dynProj :: forall f l l'. (DynCase f l) => f l' -> Maybe (f l)+dynProj x = case (dyncase x :: Maybe (l' :~: l)) of+              Just p -> Just (gcastWith p x)+              Nothing -> Nothing++-- | Inspect an existentially-quantified sort+caseE :: (DynCase f a) => E f -> Maybe (f a)+caseE = runE dynProj
+ Data/Comp/Multi/Strategy/Derive.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE TemplateHaskell #-}++module Data.Comp.Multi.Strategy.Derive (+    makeDynCase+  ) where++import Control.Arrow ( (&&&) )+import Control.Monad++import Data.Comp.Multi.Sum+import Data.Comp.Multi.Term+import Data.List ( nub )+import Data.Maybe ( catMaybes )+import Data.Type.Equality ( (:~:)(..) )++import Language.Haskell.TH hiding ( Cxt )+import Language.Haskell.TH.ExpandSyns+import Language.Haskell.TH.Lib+import Language.Haskell.TH.Syntax hiding ( Cxt )++import Data.Comp.Multi.Strategy.Classification ( KDynCase, kdyncase )+++makeDynCase :: Name -> Q [Dec]+makeDynCase fname = do+          TyConI (DataD _cxt tname targs constrs _deriving) <- abstractNewtypeQ $ reify fname+          let iVar = tyVarBndrName $ last targs+          let labs = nub $ catMaybes $ map (iTp iVar) constrs+          let cons = map (abstractConType &&& iTp iVar) constrs+          mapM (genDyn tname cons) labs+     where+       iTp :: Name -> Con -> Maybe Type+       iTp iVar (ForallC _ cxt _) =+         -- Check if the GADT phantom type is constrained+         case [y | EqualP x y <- cxt, x == VarT iVar] of+           [] -> Nothing+           tp:_ -> Just tp+       iTp _ _ = Nothing+  +       genDyn :: Name -> [((Name, Int), Maybe Type)] -> Type -> Q Dec+       genDyn tname cons tp = do+           clauses <- liftM concat $ mapM (mkClause tp) cons+           let body = [FunD 'kdyncase clauses]+           instTp  <- forallT []+                              (return [])+                              (foldl appT (conT ''KDynCase) [conT tname, return tp])+           return $ InstanceD [] instTp body+  +       mkClause :: Type -> ((Name, Int), Maybe Type) -> Q [Clause]+       mkClause tp (con, Just tp')+                   | tp == tp' = return [Clause [conPat con] +                                                (NormalB (AppE (ConE 'Just) (ConE 'Refl)))+                                                []]+       mkClause _ (con, _) = return [Clause [conPat con]+                                            (NormalB (ConE 'Nothing))+                                            []]+  +       conPat :: (Name, Int) -> Pat+       conPat (con, n) = ConP con (replicate n WildP)+++{-|+  This is the @Q@-lifted version of 'abstractNewtypeQ.+-}+abstractNewtypeQ :: Q Info -> Q Info+abstractNewtypeQ = liftM abstractNewtype++{-|+  This function abstracts away @newtype@ declaration, it turns them into+  @data@ declarations.+-}+abstractNewtype :: Info -> Info+abstractNewtype (TyConI (NewtypeD cxt name args constr derive))+    = TyConI (DataD cxt name args [constr] derive)+abstractNewtype owise = owise+++{-|+  This function provides the name and the arity of the given data constructor.+-}+abstractConType :: Con -> (Name,Int)+abstractConType (NormalC constr args) = (constr, length args)+abstractConType (RecC constr args) = (constr, length args)+abstractConType (InfixC _ constr _) = (constr, 2)+abstractConType (ForallC _ _ constr) = abstractConType constr++{-|+  This function returns the name of a bound type variable+-}+tyVarBndrName (PlainTV n) = n+tyVarBndrName (KindedTV n _) = n++++{-|+  This function provides a list (of the given length) of new names based+  on the given string.+-}+newNames :: Int -> String -> Q [Name]+newNames n name = replicateM n (newName name)+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, James Koppel++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 James Koppel nor the names of other+      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 THE COPYRIGHT+OWNER OR CONTRIBUTORS 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.
+ README.md view
@@ -0,0 +1,2 @@+# compstrat+Strategy combinators for compositional data types
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ compstrat.cabal view
@@ -0,0 +1,49 @@+Name:                compstrat+Version:             0.1.0.0+Synopsis:            Strategy combinators for compositional data types+Description:         ++    A library for strategic programming on compositional data types. See+    /The Essence of Strategic Programming/, <http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.5296&rep=rep1&type=pdf>,+    by Ralf Laemmel et al.+    +    Strategic programming is a way of allowing traversals to be written in a highly+    generic and composable fashion.+    +    The names and general interface are modeled on the KURE library,+    but this library tries to be as composable as the lens library.+    +    The type of a+    strategy combinator is the same as the /Vertical/ type+    that ekmett proposed and rejected as an extension to the current+    lens library. A /Vertical/ is essentially a monadic traversal. This hence+    could potentially be merged with the lens library.+License:             BSD3+License-File:        LICENSE+Author:              James Koppel+Maintainer:          jkoppel@mit.edu+Category:            Language, Generics+build-type:          Simple+extra-source-files:  README.md+Cabal-version:       >=1.9.2++Source-Repository head+  Type: git+  Location: https://github.com/jkoppel/compstrat++Library++  Exposed-Modules:     +                     Data.Comp.Multi.Strategic+                     Data.Comp.Multi.Strategy.Classification+                     Data.Comp.Multi.Strategy.Derive++  Build-Depends:++                     base >=4.7 && <4.8+                   , compdata < 1+                   , mtl < 2.3+                   , template-haskell+                   , th-expand-syns <= 0.4+                   , transformers < 0.5+