packages feed

yoko 0.3.0.1 → 0.3.1

raw patch · 6 files changed

+391/−22 lines, 6 filesdep +containersdep +kindsdep +mtldep ~template-haskelldep ~type-cerealdep ~type-spinePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: containers, kinds, mtl, records, th-sccs, type-functions

Dependency ranges changed: template-haskell, type-cereal, type-spine

API changes (from Hackage documentation)

- Data.Yoko: F :: a -> F a
- Data.Yoko: derive :: Name -> Q [Dec]
- Data.Yoko: encode :: Serialize a => a -> Type
- Data.Yoko: instance (Partition (DCs (Range dc)) (N dc) (DCs (Range dc) :-: N dc), Embed (N dc) (DCs (Range dc))) => IsDCOf dc
- Data.Yoko: newtype F a
+ Data.Yoko: Par2 :: (f a b) -> Par2 f a b
+ Data.Yoko: newtype Par2 f a b
+ Data.Yoko: unPar2 :: Par2 t t1 t2 -> t t1 t2
+ Data.Yoko.TH: Mapping :: Name -> Name -> Name -> Mapping
+ Data.Yoko.TH: YokoOptions :: ((String -> String) -> (String -> String)) -> ([(Int, Mapping)] -> [(Int, Mapping)]) -> YokoOptions
+ Data.Yoko.TH: containerCtor :: Mapping -> Name
+ Data.Yoko.TH: containerTypeName :: Mapping -> Name
+ Data.Yoko.TH: data Mapping
+ Data.Yoko.TH: data YokoOptions
+ Data.Yoko.TH: instance Name BindingGroup
+ Data.Yoko.TH: instance Name Mappings
+ Data.Yoko.TH: instance Name Renamer
+ Data.Yoko.TH: instance Name Target
+ Data.Yoko.TH: instance Name TargetData
+ Data.Yoko.TH: instance Name TargetKind
+ Data.Yoko.TH: instance Name TargetType
+ Data.Yoko.TH: instance Show BindingGroup
+ Data.Yoko.TH: instance Show Mappings
+ Data.Yoko.TH: instance Show Renamer
+ Data.Yoko.TH: instance Show Target
+ Data.Yoko.TH: instance Show TargetData
+ Data.Yoko.TH: instance Show TargetKind
+ Data.Yoko.TH: instance Show TargetType
+ Data.Yoko.TH: mappings :: YokoOptions -> [(Int, Mapping)] -> [(Int, Mapping)]
+ Data.Yoko.TH: methodName :: Mapping -> Name
+ Data.Yoko.TH: renamer :: YokoOptions -> (String -> String) -> (String -> String)
+ Data.Yoko.TH: yokoDefaults :: YokoOptions
+ Data.Yoko.TH: yokoTH :: Name -> Q [Dec]
+ Data.Yoko.TH: yokoTH_with :: YokoOptions -> Name -> Q [Dec]
- Data.Yoko: ig_from :: (EachGeneric (DCs t), DT t) => t -> EachRep (DCs t)
+ Data.Yoko: ig_from :: (DT t, EachGeneric (DCs t)) => t -> EachRep (DCs t)

Files

Data/Yoko.hs view
@@ -3,11 +3,15 @@   ScopedTypeVariables, UndecidableInstances #-}  module Data.Yoko-  (derive, Equal, module Data.Yoko.Representation,-   module Data.Yoko.TypeSums, module Data.Yoko, encode) where+  (Equal,+   module Data.Yoko.Representation,+   module Data.Yoko.TypeSums,+   module Data.Yoko.View,+   module Data.Yoko) where  import Data.Yoko.TypeBasics import Data.Yoko.Representation+import Data.Yoko.View import Data.Yoko.TypeSums (Embed, Partition, (:-:)) import qualified Data.Yoko.TypeSums as TypeSums import Data.Yoko.Each@@ -26,19 +30,6 @@   -type family Tag dc--type family Range dc-class (Generic dc, DT (Range dc)) => DC dc where rejoin :: dc -> Range dc--type family DCs t-type Disbanded t = DCsOf t (DCs t)-class Each IsDCOf (DCs t) => DT t where disband :: t -> Disbanded t--class (Partition (DCs (Range dc)) (N dc) (DCs (Range dc) :-: N dc),-       Embed (N dc) (DCs (Range dc))) => IsDCOf dc-instance (Partition (DCs (Range dc)) (N dc) (DCs (Range dc) :-: N dc),-          Embed (N dc) (DCs (Range dc))) => IsDCOf dc   
Data/Yoko/Representation.hs view
@@ -8,7 +8,6 @@   data U = U-newtype F a = F a infixr 6 :*: data a :*: b = a :*: b @@ -20,6 +19,7 @@   newtype Par1 f a = Par1 (f a)+newtype Par2 f a b = Par2 (f a b)   @@ -41,6 +41,7 @@ mapRec f (Rec x) = Rec (f x)  unPar1 (Par1 x) = x+unPar2 (Par2 x) = x  unN (N x) = x foldN f = f . unN
+ Data/Yoko/TH.hs view
@@ -0,0 +1,310 @@+{-# LANGUAGE TypeOperators, ViewPatterns, TemplateHaskell, PatternGuards #-}++module Data.Yoko.TH+  (yokoTH, yokoTH_with, yokoDefaults, YokoOptions(..), Mapping(..)) where++import Type.Spine.Stage0 (Spine, spineType_, kTypeG)+import Type.Serialize (serializeTypeAsHash_)+import qualified Type.Ord as Ord++import Data.Yoko.TypeBasics (encode)+import Data.Yoko.Representation+import Data.Yoko.View++import Language.Haskell.TH as TH hiding (Range)+import Language.Haskell.TH.Syntax as TH hiding (Range)+import qualified Language.Haskell.TH.SCCs as SCCs++import qualified Data.Yoko.TH.Internal as Int++import qualified Control.Monad.Writer as Writer+import qualified Control.Monad.Trans as Trans++import qualified Control.Arrow as Arrow++import Data.Set (Set)+import qualified Data.Set as Set+import qualified Data.List as List++import Data.Kind (KindStar(..))+import Data.TypeFun+import Data.Record hiding (convert, Name)+import qualified Data.Record as R+import qualified Data.Record.Combinators as R+import Data.Record.Combinators ((!!!))++++++convert r = R.convert $ R.withStyle r (Id KindStar)++data Target = Target deriving Show+data Renamer = Renamer deriving Show+data Mappings = Mappings deriving Show+data BindingGroup = BindingGroup deriving Show+data TargetData = TargetData deriving Show+data TargetType = TargetType deriving Show+data TargetKind = TargetKind deriving Show+instance R.Name Target where name = Target+instance R.Name Renamer where name = Renamer+instance R.Name Mappings where name = Mappings+instance R.Name BindingGroup where name = BindingGroup+instance R.Name TargetData where name = TargetData+instance R.Name TargetType where name = TargetType+instance R.Name TargetKind where name = TargetKind++++data Mapping = Mapping+  {containerTypeName :: Name, containerCtor :: Name,+   methodName :: Name}++data YokoOptions = YokoOptions+  {renamer :: (String -> String) -> (String -> String),+   mappings :: [(Int, Mapping)] -> [(Int, Mapping)]}++yokoDefaults :: YokoOptions+yokoDefaults = YokoOptions id id++type M r = Writer.WriterT [Dec] Q++liftQ :: Q a -> M r a+liftQ = Trans.lift++runM :: M r () -> Q [Dec]+runM = fmap snd . Writer.runWriterT++generate :: [Dec] -> M r ()+generate = Writer.tell++++yokoTH :: Name -> Q [Dec]+yokoTH n = yokoTH_with yokoDefaults n++yokoTH_with :: YokoOptions -> Name -> Q [Dec]+yokoTH_with options n = runM $ yoko0 $ X :&+  Target := n :& Renamer := (mkName . renamer options (++ "_") . TH.nameBase)+         :& Mappings := mappings options [(1, Mapping ''Par1 'Par1 'fmap)]+++++-- gather reflective information about the target type+yoko0 r@(convert -> X :& Target := n) = do+  names <- liftQ $ SCCs.binding_group n+  datatype@(Int.DataType tvbs _) <- liftQ $ Int.dataType n++  let ty = applyConT2TVBs n tvbs++  -- get the kind of the target type; each fields type has the same kind+  cxt <- flip mapM tvbs $ \tvb -> liftQ $+    EqualP (ConT ''Ord.EQ) `fmap` do+      let tv = [t| Spine ($(kTypeG (tvbKind tvb)) $(return $ tvbType tvb)) |]+      [t| Ord.Compare $tv $tv |]++  yoko1 $ r :&+    BindingGroup := names :&+    TargetData := datatype :&+    TargetType := ty :&+    TargetKind := (map tvbKind tvbs, cxt)++-- generate fields types+conName :: Con -> Name+conName (NormalC n _) = n+conName (RecC n _) = n+conName (InfixC _ n _) = n+conName (ForallC _ _ c) = conName c++renameCon :: (Name -> Name) -> Con -> Con+renameCon f (NormalC n fields) = NormalC (f n) fields+renameCon f (RecC n fields) = RecC (f n) fields+renameCon f (InfixC fieldL n fieldR) = InfixC fieldL (f n) fieldR+renameCon f (ForallC tvbs cxt c) = ForallC tvbs cxt $ renameCon f c++tvbName :: TyVarBndr -> Name+tvbName (PlainTV n) = n+tvbName (KindedTV n _) = n++tvbKind :: TyVarBndr -> Kind+tvbKind (PlainTV _) = StarK+tvbKind (KindedTV _ k) = k++tvbType :: TyVarBndr -> Type+tvbType = VarT . tvbName++applyConT2TVBs :: Name -> [TyVarBndr] -> Type+applyConT2TVBs n tvbs = foldl ((. tvbType) . AppT) (ConT n) tvbs++conFields :: Con -> Q [StrictType]+conFields (NormalC _ fds)    = return fds+conFields (RecC _ fds)       = return $ map (\(_, x, y) -> (x, y)) fds+conFields (InfixC fdl _ fdr) = return [fdl, fdr]+conFields ForallC{}          = Int.thFail "no support for existential types."++pat_exp :: Name -> Name -> Int -> (Pat, Exp)+pat_exp np ne k = (ConP np $ map VarP ns,+                   foldl ((. VarE) . AppE) (ConE ne) ns) where+  ns = [ mkName $ "x" ++ show i | i <- [0..k - 1] ]++simpleClause pats exp = Clause pats (NormalB exp) []++halves :: [a] -> b -> (b -> b -> b) -> (a -> b) -> b+halves as nil app each = w (length as) as where+  w _ []  = nil+  w _ [a] = each a+  w k as  = w lk l `app` w rk r+    where lk = k `div` 2   ;   rk = k - lk+          (l, r) = List.splitAt lk as++peelApp :: Type -> (Type, [Type])+peelApp = peelAppAcc []++peelAppAcc acc (AppT ty0 ty1) = peelAppAcc (ty1 : acc) ty0+peelAppAcc acc ty             = (ty, acc)++data FieldRO = FieldRO {repF :: Exp, objF :: Exp}++fieldRO :: [(Int, Mapping)] -> Set Name -> Type -> Q (Type, FieldRO)+fieldRO maps bg = w' where+  w' = uncurry w . peelApp++  isRec n = Set.member n bg++  simple b ty tys = return $ (ConT tyn `AppT` foldl AppT ty tys,+    if b then FieldRO (ConE 'Rec) (VarE 'unRec)+         else FieldRO (ConE 'Dep) (VarE 'unDep))+    where tyn = if b then ''Rec else ''Dep++  w ty tys = case ty of+    AppT{}              -> Int.thFail $ "impossible: AppT is guarded by peelApp."+    SigT ty _           -> uncurry w $ peelAppAcc tys ty+    ForallT{}           -> Int.thFail $ "no support for ForallT."+    ConT n+      | isRec n -> if not (null recs) then Int.thFail "does not support nested recursion."+                   else simple True ty tys+    _ +      | not (null recs) -> case lookup (length recs) maps of+        Nothing -> Int.thFail $ "no case in the given YokoOptions for type constructors with " ++ show (length recs) ++ " arguments."+        Just (Mapping {containerTypeName = tyn, containerCtor = ctor,+                       methodName = mn}) -> do+          recs <- mapM w' recs+          let snoc (tyL, fROL) (tyR, fROR) =+                (tyL `AppT` tyR, fROL `appRO` fROR)+              appRO l r = FieldRO {repF = repF l `AppE` repF r,+                                   objF = objF l `AppE` objF r}+              post fRO = FieldRO {repF = ConE ctor `compose` repF fRO,+                                  objF = objF fRO `compose` dtor}+          return $ Arrow.second post $ foldl snoc+            (ConT tyn `AppT` container,+             FieldRO {repF = VarE mn, objF = VarE mn}) recs+          where dtor = LamE [ConP ctor [VarP x]] (VarE x)+                  where x = mkName "x"+      | otherwise -> simple False ty tys+    where (foldl AppT ty -> container, recs) =+            List.break (any isRec . Set.toList . SCCs.type_dependencies) tys++data ConRO = ConRO {repP :: [Pat], repE :: Exp, objP :: Pat, objE :: [Exp]}++yoko1 r@(convert -> X :&+  Renamer := rn :&+  Mappings := maps :&+  BindingGroup := bg :&+  TargetData := Int.DataType tvbs cons :&+  TargetType := ty :&+  TargetKind := (ks, cxt)+        ) = do+  loc <- liftQ TH.location++  -- make a name into a NameG for a type in the current module; NB the fields+  -- types need not be declared in the same module as the target type+  let mkG n = Name (mkOccName $ nameBase n) $+              NameG TcClsName (mkPkgName $ loc_package loc)+                      (mkModName $ loc_module loc)++  liftQ (sequence [do+    let n = conName con+        n' = rn n+        fd = applyConT2TVBs n' tvbs++    fields <- conFields con++    -- declare the fields type and its Range/Tag/DC instances+    let yokoD = +          [Int.dataType2Dec n' (Int.DataType tvbs (Right [renameCon rn con])),+           TySynInstD ''Range [fd] ty,+           TySynInstD ''Tag   [fd] $ encode $ TH.nameBase n,+           InstanceD cxt (ConT ''DC `AppT` fd)+             [let (pat, exp) = pat_exp n' n $ length fields+              in FunD 'rejoin [simpleClause [pat] exp]]+          ]++    -- declare the Rep and Generic instances+    (repTy, (conRO, _)) <- Arrow.second ($ 0) `fmap` halves fields+          (return (ConT ''U, \s ->+                   (ConRO {repP = [], repE = ConE 'U,+                           objP = WildP, objE = []}, s)))+          (\l r -> l >>= \(tyL, roL) -> r >>= \(tyR, roR) -> return $+            (ConT ''(:*:) `AppT` tyL `AppT` tyR,+             \s -> case roL s of+               (roL, s) -> case roR s of+                 (roR, s) ->+                   (ConRO {repP = repP roL ++ repP roR,+                           repE = ConE '(:*:) `AppE` repE roL `AppE` repE roR,+                           objP = ConP '(:*:) [objP roL, objP roR],+                           objE = objE roL ++ objE roR}, s)))+          (\(_, ty) ->+             let post fRO s =+                   (ConRO {repP = [VarP n], repE = repF fRO `AppE` VarE n,+                           objP = VarP n, objE = [objF fRO `AppE` VarE n]},+                    s + 1)+                   where n = mkName $ "x" ++ show s+             in Arrow.second post `fmap` fieldRO maps bg ty)++    let genD = [TySynInstD ''Rep [fd] repTy,+                InstanceD cxt (ConT ''Generic `AppT` fd)+                 [FunD 'rep [simpleClause [ConP n' (repP conRO)] $ repE conRO],+                  FunD 'obj [simpleClause [objP conRO] $+                               foldl AppE (ConE n') $ objE conRO]]]++    -- integrate with type-spine and type-cereal+    spineD <- spineType_ (mkG n') ks StarK+    cerealD <- serializeTypeAsHash_ (mkG n') ks StarK++    return $ yokoD ++ spineD ++ cerealD ++ genD+       | con <- either (:[]) id cons ]) >>= generate . concat++  yoko2 r++-- generate DCs/DT instances+compose l r = VarE '(.) `AppE` l `AppE` r++postConE :: Name -> Exp -> Exp+postConE n inj = compose (ConE n) inj++yoko2 r@(convert -> X :&+  Renamer := rn :&+  TargetData := Int.DataType tvbs cons :&+  TargetType := ty :&+  TargetKind := (_, cxt)+        ) = do+  (dcs, cases) <- liftQ $ halves (either (:[]) id cons)+    (Int.thFail $ "`" ++ show (r !!! Target :: Name) ++ "' must have constructors.")+    (\l r -> do+      (l, ls) <- l; (r, rs) <- r+      return $+        (ConT ''(:+:) `AppT` l `AppT` r,+         map (Arrow.first (postConE 'L)) ls +++         map (Arrow.first (postConE 'R)) rs))+    (\con -> do+       fields <- length `fmap` conFields con+       return $ let n = conName con+                in (ConT ''N `AppT` applyConT2TVBs (rn n) tvbs,+                    [(ConE 'N, (n, fields))]))++  cases <- return $ flip map cases $ \(inj, (n, fds)) ->+    let (pat, exp) = pat_exp n (rn n) fds+    in simpleClause [pat] $ postConE 'DCsOf inj `AppE` exp+  generate $ [TySynInstD ''DCs [ty] dcs,+              InstanceD cxt (ConT ''DT `AppT` ty) [FunD 'disband cases]]
+ Data/Yoko/TH/Internal.hs view
@@ -0,0 +1,29 @@+module Data.Yoko.TH.Internal where++import Language.Haskell.TH++++thFail :: String -> Q a+thFail s = fail $ "yokoTH: " ++ s++++data DataType = DataType [TyVarBndr] (Either Con [Con])++++dataType :: Name -> Q DataType+dataType n = do+  i <- reify n+  case i of+    TyConI d -> case d of+      DataD _ _ tvbs cons _   -> return $ DataType tvbs $ Right cons+      NewtypeD _ _ tvbs con _ -> return $ DataType tvbs $ Left con+      _ -> thFail $ "expecting name of newtype or data type, not: " ++ show d+    _ -> thFail $ "expecting name of newtype or data type, not: " ++ show i++dataType2Dec :: Name -> DataType -> Dec+dataType2Dec n (DataType tvbs cons) = case cons of+  Left  con  -> NewtypeD [] n tvbs con  []+  Right cons -> DataD    [] n tvbs cons []
+ Data/Yoko/View.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE TypeFamilies, TypeOperators, FlexibleContexts,+  MultiParamTypeClasses, FlexibleInstances, ConstraintKinds,+  UndecidableInstances #-}++module Data.Yoko.View where++import Data.Yoko.Representation+import Data.Yoko.TypeSums (Embed, Partition, (:-:))+import Data.Yoko.Each++++++type family Tag dc++type family Range dc+class (Generic dc, DT (Range dc)) => DC dc where rejoin :: dc -> Range dc++type family DCs t+type Disbanded t = DCsOf t (DCs t)+class Each IsDCOf (DCs t) => DT t where disband :: t -> Disbanded t++class (Partition (DCs (Range dc)) (N dc) (DCs (Range dc) :-: N dc),+       Embed (N dc) (DCs (Range dc))) => IsDCOf dc+instance (Partition (DCs (Range dc)) (N dc) (DCs (Range dc) :-: N dc),+          Embed (N dc) (DCs (Range dc))) => IsDCOf dc
yoko.cabal view
@@ -1,5 +1,5 @@ name: yoko-version: 0.3.0.1+version: 0.3.1 synopsis: Generic Programming with Disbanded Data Types  description:@@ -81,28 +81,39 @@   library-  build-depends: base >= 4 && < 5, template-haskell+  build-depends: base >= 4 && < 5,+                 template-haskell > 2.7 && < 2.8,+                 containers >= 0.4 && < 0.5,+                 mtl >= 2.0 && < 2.1   build-depends: type-equality < 0.2    build-depends:+    kinds >= 0.0.1.5 && < 0.1,+    type-functions >= 0.2.0.3 && < 0.3,+    records >= 0.1.1.6 && < 0.2++  build-depends:+    th-sccs < 0.1,     type-booleans < 0.2,-    type-spine < 0.2,+    type-spine >= 0.1.1 && < 0.2,     tagged-th < 0.2,     type-digits < 0.2,-    type-cereal < 0.2,+    type-cereal >= 0.1.1 && < 0.2,     type-ord < 0.2,     type-ord-spine-cereal < 0.2    exposed-modules:-    Data.Yoko, Data.Yoko.HCompos,+    Data.Yoko, Data.Yoko.HCompos, Data.Yoko.TH      Data.Yoko.TypeBasics, Data.Yoko.Each    other-modules:+    Data.Yoko.View,     Data.Yoko.MaybeKind,     Data.Yoko.Representation,     Data.Yoko.TypeSums,-    Data.Yoko.TypeSumsAux+    Data.Yoko.TypeSumsAux,+    Data.Yoko.TH.Internal      -- under development --    Data.Yoko.Fold,