on master help sign in
WIP typed traversals
commit11eb64973a9e1acf3e698309eb7a46fd8609fe40 authorCsongor Kiss <kiss.csongor.kiss@gmail.com> dateMon 30 Oct 2017, 13:26 (9 years ago) parent3394129
7 files changed+119−3
generic-lens.cabal+2 src/Data/Generics/Internal/Lens.hs+4 src/Data/Generics/Product.hs+2 src/Data/Generics/Product/Internal/Types.hs+54 src/Data/Generics/Product/Typed.hs+1−1 src/Data/Generics/Product/Types.hs+49 test/Spec.hs+7−2
generic-lens.cabal+2
@@ -26,6 +26,7 @@ library
2626 , Data.Generics.Product.Subtype
2727 , Data.Generics.Product.Typed
2828 , Data.Generics.Labels
29+ , Data.Generics.Product.Types
2930
3031 , Data.Generics.Sum
3132 , Data.Generics.Sum.Any
@@ -49,6 +50,7 @@ library
4950 , Data.Generics.Product.Internal.Positions
5051 , Data.Generics.Product.Internal.Subtype
5152 , Data.Generics.Product.Internal.Typed
53+ , Data.Generics.Product.Internal.Types
5254
5355 build-depends: base >= 4.9 && <= 5.0
5456 , profunctors >= 5.0 && <= 6.0
src/Data/Generics/Internal/Lens.hs+4
@@ -32,6 +32,10 @@ type Lens' s a
3232type Lens s t a b
3333 = forall f. Functor f => (a -> f b) -> s -> f t
3434
35+-- | Type alias for traversal
36+type Traversal' s a
37+ = forall f. Applicative f => (a -> f a) -> s -> f s
38+
3539-- | Type alias for prism
3640type Prism s t a b
3741 = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
src/Data/Generics/Product.hs+2
@@ -22,6 +22,7 @@ module Data.Generics.Product
2222 , module Data.Generics.Product.Positions
2323 , module Data.Generics.Product.Subtype
2424 , module Data.Generics.Product.Typed
25+ , module Data.Generics.Product.Types
2526 ) where
2627
2728import Data.Generics.Product.Any
@@ -29,3 +30,4 @@ import Data.Generics.Product.Fields
2930import Data.Generics.Product.Positions
3031import Data.Generics.Product.Subtype
3132import Data.Generics.Product.Typed
33+import Data.Generics.Product.Types
src/Data/Generics/Product/Internal/Types.hsnew file+54
@@ -0,0 +1,54 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE KindSignatures #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE ScopedTypeVariables #-}
8+{-# LANGUAGE TypeApplications #-}
9+{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE TypeOperators #-}
11+{-# LANGUAGE UndecidableInstances #-}
12+
13+-----------------------------------------------------------------------------
14+-- |
15+-- Module : Data.Generics.Product.Internal.Types
16+-- Copyright : (C) 2017 Csongor Kiss
17+-- License : BSD3
18+-- Maintainer : Csongor Kiss <kiss.csongor.kiss@gmail.com>
19+-- Stability : experimental
20+-- Portability : non-portable
21+--
22+-- Derive traversals of a given type in a product.
23+--
24+-----------------------------------------------------------------------------
25+
26+module Data.Generics.Product.Internal.Types
27+ ( GHasTypes (..)
28+ ) where
29+
30+--import Data.Generics.Internal.Families
31+import Data.Generics.Internal.Lens
32+
33+import Data.Kind (Type)
34+import GHC.Generics
35+
36+-- |As 'HasTypes' but over generic representations as defined by
37+-- "GHC.Generics".
38+class GHasTypes (f :: Type -> Type) a where
39+ gtypes :: Traversal' (f x) a
40+
41+instance (GHasTypes l a, GHasTypes r a) => GHasTypes (l :*: r) a where
42+ gtypes f (l :*: r) = (:*:) <$> gtypes f l <*> gtypes f r
43+
44+-- TODO:
45+-- instance (GHasTypes l a, GHasTypes r a) => GHasTypes (l :+: r) a where
46+
47+instance GHasTypes (K1 R a) a where
48+ gtypes f (K1 x) = fmap K1 (f x)
49+
50+instance {-# OVERLAPS #-} GHasTypes (K1 R a) b where
51+ gtypes _ k = pure k
52+
53+instance GHasTypes f a => GHasTypes (M1 m meta f) a where
54+ gtypes = mIso . gtypes
src/Data/Generics/Product/Typed.hs+1−1
@@ -19,7 +19,7 @@
1919-- Stability : experimental
2020-- Portability : non-portable
2121--
22−-- Derive record field getters and setters generically.
22+-- Derive lenses of a given type in a product.
2323--
2424-----------------------------------------------------------------------------
2525
src/Data/Generics/Product/Types.hsnew file+49
@@ -0,0 +1,49 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE KindSignatures #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE ScopedTypeVariables #-}
8+{-# LANGUAGE TypeApplications #-}
9+{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE TypeOperators #-}
11+{-# LANGUAGE UndecidableInstances #-}
12+
13+-----------------------------------------------------------------------------
14+-- |
15+-- Module : Data.Generics.Product.Types
16+-- Copyright : (C) 2017 Csongor Kiss
17+-- License : BSD3
18+-- Maintainer : Csongor Kiss <kiss.csongor.kiss@gmail.com>
19+-- Stability : experimental
20+-- Portability : non-portable
21+--
22+-- Derive traversals of a given type in a product.
23+--
24+-----------------------------------------------------------------------------
25+
26+module Data.Generics.Product.Types
27+ ( -- *Traversals
28+ --
29+ -- $example
30+ HasTypes (..)
31+ ) where
32+
33+--import Data.Generics.Internal.Families
34+import Data.Generics.Internal.Lens
35+import Data.Generics.Product.Internal.Types
36+
37+--import Data.Kind (Constraint, Type)
38+import GHC.Generics (Generic (Rep))
39+--import GHC.TypeLits (TypeError, ErrorMessage (..))
40+
41+class HasTypes a s where
42+ types :: Traversal' s a
43+
44+instance
45+ ( Generic s
46+ , GHasTypes (Rep s) a
47+ ) => HasTypes a s where
48+
49+ types = repIso . gtypes
test/Spec.hs+7−2
@@ -45,8 +45,7 @@ prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
4545prism bt seta = dimap seta (either pure (fmap bt)) . right'
4646{-# INLINE prism #-}
4747
48−fieldALensManual :: Lens' Record Int
49−fieldALensManual f (MkRecord a b) = (\a' -> MkRecord a' b) <$> f a
48+type Traversal' s a = forall f. Applicative f => (a -> f a) -> s -> f s
5049
5150typeChangingManual :: Lens (Record3 a) (Record3 b) a b
5251typeChangingManual f (MkRecord3 a b) = (\a' -> MkRecord3 a' b) <$> f a
@@ -56,6 +55,12 @@ typeChangingManualCompose = typeChangingManual . typeChangingManual
5655
5756newtype L s a = L (Lens' s a)
5857
58+intTraversalManual :: Traversal' Record3 Int
59+intTraversalManual = types
60+
61+fieldALensManual :: Lens' Record Int
62+fieldALensManual f (MkRecord a b) = (\a' -> MkRecord a' b) <$> f a
63+
5964subtypeLensManual :: Lens' Record Record2
6065subtypeLensManual f record
6166 = fmap (\ds -> case record of