packages feed

fclabels 0.4.1 → 0.4.2

raw patch · 5 files changed

+193/−180 lines, 5 filesdep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: template-haskell

API changes (from Hackage documentation)

+ Data.Record.Label: fmapL :: (Applicative f) => (a :-> b) -> f a :-> f b
+ Data.Record.Label: lmap :: (Functor f) => (a :<->: b) -> f a :<->: f b

Files

− Data/Record/Label.hs
@@ -1,143 +0,0 @@-{-# LANGUAGE TypeOperators, TypeSynonymInstances, TemplateHaskell #-}-module Data.Record.Label-  (-  -- * Getter, setter and modifier types.-    Getter-  , Setter-  , Modifier--  -- * Label type.-  , Point-  , (:->) (Label)-  , label-  , get, set, mod--  -- * Bidirectional functor.-  , (:<->:) (..)-  , (<->)-  , Iso (..)-  , for--  -- * State monadic label operations.--  , getM, setM, modM, (=:)--  -- * Derive labels using Template Haskell.-  , module Data.Record.Label.TH-  )-where--import Prelude hiding ((.), id, mod)-import Control.Applicative-import Control.Category-import Control.Monad.State hiding (get)-import Data.Record.Label.TH--type Getter   f o   = f -> o-type Setter   f i   = i -> f -> f-type Modifier f i o = (o -> i) -> f -> f--data Point f i o = Point-  { _get :: Getter f o-  , _set :: Setter f i-  }--_mod :: Point f i o -> (o -> i) -> f -> f-_mod l f a = _set l (f (_get l a)) a--newtype (f :-> a) = Label { unLabel :: Point f a a }---- Create a label out of a getter and setter.--label :: Getter f a -> Setter f a -> f :-> a-label g s = Label (Point g s)---- | Get the getter function from a label.--get :: (f :-> a) -> f -> a-get = _get . unLabel---- | Get the setter function from a label.--set :: (f :-> a) -> a -> f -> f-set = _set . unLabel---- | Get the modifier function from a label.--mod :: (f :-> a) -> (a -> a) -> f -> f-mod = _mod . unLabel--instance Category (:->) where-  id = Label (Point id const)-  (Label a) . (Label b) = Label (Point (_get a . _get b) (_mod b . _set a))--instance Functor (Point f i) where-  fmap f x = Point (f . _get x) (_set x)--instance Applicative (Point f i) where-  pure a = Point (const a) (const id)-  a <*> b = Point (\f -> _get a f (_get b f)) (\r -> _set b r . _set a r)---- | This isomorphism type class is like a `Functor' but works in two directions.--class Iso f where-  iso :: a :<->: b -> f a -> f b-  iso (Lens a b) = osi (b <-> a)-  osi :: a :<->: b -> f b -> f a-  osi (Lens a b) = iso (b <-> a)---- | The lens datatype, a function that works in two directions. To bad there--- is no convenient way to do application for this.--data a :<->: b = Lens { fw :: a -> b, bw :: b -> a }---- | Constructor for lenses.--infixr 7 <->-(<->) :: (a -> b) -> (b -> a) -> a :<->: b-a <-> b = Lens a b--instance Category (:<->:) where-  id = Lens id id-  (Lens a b) . (Lens c d) = Lens (a . c) (d . b)--instance Iso ((:->) i) where-  iso l (Label a) = Label (Point (fw l . _get a) (_set a . bw l))--instance Iso ((:<->:) i) where-  iso = (.)--dimap :: (o' -> o) -> (i -> i') -> Point f i' o' -> Point f i o-dimap f g l = Point (f . _get l) (_set l . g)---- | Combine a partial destructor with a label into something easily used in--- the applicative instance for the hidden `Point' datatype. Internally uses--- the covariant in getter, contravariant in setter bi-functioral-map function.--- (Please refer to the example because this function is just not explainable--- on its own.)--for :: (i -> o) -> (f :-> o) -> Point f i o-for a b = dimap id a (unLabel b)---- | Get a value out of state pointed to by the specified label.--getM :: MonadState s m => s :-> b -> m b-getM = gets . get---- | Set a value somewhere in state pointed to by the specified label.--setM :: MonadState s m => s :-> b -> b -> m ()-setM l = modify . set l---- | Alias for `setM' that reads like an assignment.--infixr 7 =:-(=:) :: MonadState s m => s :-> b -> b -> m ()-(=:) = setM---- | Modify a value with a function somewhere in state pointed to by the--- specified label.--modM :: MonadState s m => s :-> b -> (b -> b) -> m ()-modM l = modify . mod l-
− Data/Record/Label/TH.hs
@@ -1,35 +0,0 @@-module Data.Record.Label.TH (mkLabels) where--import Control.Monad-import Data.Char-import Language.Haskell.TH.Syntax---- | Derive labels for all the record selector in a datatype.-mkLabels :: [Name] -> Q [Dec]-mkLabels = liftM concat . mapM mkLabels1--mkLabels1 :: Name -> Q [Dec]-mkLabels1 n = do-    i <- reify n-    let -- only process data declarations-        cs' = case i of { TyConI (DataD _ _ _ cs _) -> cs ; _ -> [] }-        -- we're only interested in labels of record constructors-        ls' = [ l | RecC _ ls <- cs', l <- ls ]-    return (map mkLabel1 ls')--mkLabel1 :: VarStrictType -> Dec-mkLabel1 (name, _, _) =-    -- Generate a name for the label:-    -- If the original selector starts with an _, remove it and make the next-    -- character lowercase.  Otherwise, add 'l', and make the next character-    -- uppercase.-    let n = mkName $ case nameBase name of-                ('_' : c : rest) -> toLower c : rest-                (f : rest)       -> 'l' : toUpper f : rest-                _                -> ""-    in FunD n [Clause [] (NormalB (-           AppE (AppE (VarE (mkName "label")) (VarE name)) -- getter-                (LamE [VarP (mkName "b"), VarP (mkName "a")] -- setter-                      (RecUpdE (VarE (mkName "a")) [(name, VarE (mkName "b"))]))-                                   )) []]-
fclabels.cabal view
@@ -1,5 +1,5 @@ Name:            fclabels-Version:         0.4.1+Version:         0.4.2 Author:          Sebastiaan Visser, Erik Hesselink, Chris Eidhof, Sjoerd Visscher. Synopsis:        First class accessor labels. @@ -135,7 +135,8 @@ Category:        Data Build-Type:      Simple Cabal-Version:   >= 1.6+HS-Source-Dirs:  src Exposed-Modules: Data.Record.Label Other-Modules:   Data.Record.Label.TH-Build-Depends:   base >= 3 && < 5, template-haskell >= 2.2 && < 2.4, monads-fd ==0.0.*+Build-Depends:   base >= 3 && < 5, template-haskell >= 2.2 && < 2.5, monads-fd ==0.0.* 
+ src/Data/Record/Label.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE TypeOperators, TypeSynonymInstances, TemplateHaskell #-}+module Data.Record.Label+  (+  -- * Getter, setter and modifier types.+    Getter+  , Setter+  , Modifier++  -- * Label type.+  , Point+  , (:->) (Label)+  , label+  , get, set, mod++  , fmapL++  -- * Bidirectional functor.+  , (:<->:) (..)+  , (<->)+  , Iso (..)+  , lmap+  , for++  -- * State monadic label operations.++  , getM, setM, modM, (=:)++  -- * Derive labels using Template Haskell.+  , module Data.Record.Label.TH+  )+where++import Prelude hiding ((.), id, mod)+import Control.Applicative+import Control.Category+import Control.Monad.State hiding (get)+import Data.Record.Label.TH++type Getter   f o   = f -> o+type Setter   f i   = i -> f -> f+type Modifier f i o = (o -> i) -> f -> f++data Point f i o = Point+  { _get :: Getter f o+  , _set :: Setter f i+  }++_mod :: Point f i o -> (o -> i) -> f -> f+_mod l f a = _set l (f (_get l a)) a++newtype (f :-> a) = Label { unLabel :: Point f a a }++-- Create a label out of a getter and setter.++label :: Getter f a -> Setter f a -> f :-> a+label g s = Label (Point g s)++-- | Get the getter function from a label.++get :: (f :-> a) -> f -> a+get = _get . unLabel++-- | Get the setter function from a label.++set :: (f :-> a) -> a -> f -> f+set = _set . unLabel++-- | Get the modifier function from a label.++mod :: (f :-> a) -> (a -> a) -> f -> f+mod = _mod . unLabel++instance Category (:->) where+  id = Label (Point id const)+  (Label a) . (Label b) = Label (Point (_get a . _get b) (_mod b . _set a))++instance Functor (Point f i) where+  fmap f x = Point (f . _get x) (_set x)++instance Applicative (Point f i) where+  pure a = Point (const a) (const id)+  a <*> b = Point (_get a <*> _get b) (\r -> _set b r . _set a r)++fmapL :: Applicative f => (a :-> b) -> f a :-> f b+fmapL l = label (fmap (get l)) (\x f -> set l <$> x <*> f)++-- | This isomorphism type class is like a `Functor' but works in two directions.++class Iso f where+  iso :: a :<->: b -> f a -> f b+  iso (Lens a b) = osi (b <-> a)+  osi :: a :<->: b -> f b -> f a+  osi (Lens a b) = iso (b <-> a)++-- | The lens datatype, a function that works in two directions. To bad there+-- is no convenient way to do application for this.++data a :<->: b = Lens { fw :: a -> b, bw :: b -> a }++-- | Constructor for lenses.++infixr 7 <->+(<->) :: (a -> b) -> (b -> a) -> a :<->: b+a <-> b = Lens a b++instance Category (:<->:) where+  id = Lens id id+  (Lens a b) . (Lens c d) = Lens (a . c) (d . b)++instance Iso ((:->) i) where+  iso l (Label a) = Label (Point (fw l . _get a) (_set a . bw l))++instance Iso ((:<->:) i) where+  iso = (.)++lmap :: Functor f => (a :<->: b) -> f a :<->: f b +lmap l = let (Lens a b) = l in fmap a <-> fmap b++dimap :: (o' -> o) -> (i -> i') -> Point f i' o' -> Point f i o+dimap f g l = Point (f . _get l) (_set l . g)++-- | Combine a partial destructor with a label into something easily used in+-- the applicative instance for the hidden `Point' datatype. Internally uses+-- the covariant in getter, contravariant in setter bi-functioral-map function.+-- (Please refer to the example because this function is just not explainable+-- on its own.)++for :: (i -> o) -> (f :-> o) -> Point f i o+for a b = dimap id a (unLabel b)++-- | Get a value out of state pointed to by the specified label.++getM :: MonadState s m => s :-> b -> m b+getM = gets . get++-- | Set a value somewhere in state pointed to by the specified label.++setM :: MonadState s m => s :-> b -> b -> m ()+setM l = modify . set l++-- | Alias for `setM' that reads like an assignment.++infixr 7 =:+(=:) :: MonadState s m => s :-> b -> b -> m ()+(=:) = setM++-- | Modify a value with a function somewhere in state pointed to by the+-- specified label.++modM :: MonadState s m => s :-> b -> (b -> b) -> m ()+modM l = modify . mod l+
+ src/Data/Record/Label/TH.hs view
@@ -0,0 +1,38 @@+module Data.Record.Label.TH (mkLabels) where++import Control.Monad+import Data.Char+import Language.Haskell.TH.Syntax++-- | Derive labels for all the record selector in a datatype.+mkLabels :: [Name] -> Q [Dec]+mkLabels = liftM concat . mapM mkLabels1++mkLabels1 :: Name -> Q [Dec]+mkLabels1 n = do+    i <- reify n+    let -- only process data and newtype declarations+        cs' = case i of+                TyConI (DataD _ _ _ cs _)   -> cs+                TyConI (NewtypeD _ _ _ c _) -> [c]+                _ -> []+        -- we're only interested in labels of record constructors+        ls' = [ l | RecC _ ls <- cs', l <- ls ]+    return (map mkLabel1 ls')++mkLabel1 :: VarStrictType -> Dec+mkLabel1 (name, _, _) =+    -- Generate a name for the label:+    -- If the original selector starts with an _, remove it and make the next+    -- character lowercase.  Otherwise, add 'l', and make the next character+    -- uppercase.+    let n = mkName $ case nameBase name of+                ('_' : c : rest) -> toLower c : rest+                (f : rest)       -> 'l' : toUpper f : rest+                _                -> ""+    in FunD n [Clause [] (NormalB (+           AppE (AppE (VarE (mkName "label")) (VarE name)) -- getter+                (LamE [VarP (mkName "b"), VarP (mkName "a")] -- setter+                      (RecUpdE (VarE (mkName "a")) [(name, VarE (mkName "b"))]))+                                   )) []]+