on master help sign in
Optimise 'field' lens with Coyoneda
5da262dCsongor Kiss
src/Data/Generics/Internal/Lens.hs+19−1
@@ -1,4 +1,5 @@
1+{-# LANGUAGE GADTs #-}
1−{-# LANGUAGE Rank2Types #-}
2+{-# LANGUAGE Rank2Types #-}
2{-# LANGUAGE TypeOperators #-}
3{-# LANGUAGE TypeOperators #-}
3
4
4-----------------------------------------------------------------------------
5-----------------------------------------------------------------------------
@@ -89,3 +90,20 @@ _Left = prism Left $ either Right (Left . Right)
89
90
90_Right :: Prism' (Either c a) a
91_Right :: Prism' (Either c a) a
91_Right = prism Right $ either (Left . Left) Right
92_Right = prism Right $ either (Left . Left) Right
93+
94+--------------------------------------------------------------------------------
95+
96+data Coyoneda f b = forall a. Coyoneda (a -> b) (f a)
97+
98+instance Functor (Coyoneda f) where
99+ fmap f (Coyoneda g fa)
100+ = Coyoneda (f . g) fa
101+
102+inj :: Functor f => Coyoneda f a -> f a
103+inj (Coyoneda f a) = fmap f a
104+
105+proj :: Functor f => f a -> Coyoneda f a
106+proj fa = Coyoneda id fa
107+
108+ravel :: Functor f => ((a -> Coyoneda f b) -> s -> Coyoneda f t) -> (a -> f b) -> (s -> f t)
109+ravel coy f s = inj $ coy (\a -> proj (f a)) s
src/Data/Generics/Product/Fields.hs+1−1
@@ -91,7 +91,7 @@ instance
91 , GHasField field (Rep s) a
91 , GHasField field (Rep s) a
92 ) => HasField field a s where
92 ) => HasField field a s where
93
93
94− field = repIso . gfield @field
94+ field = ravel (repIso . gfield @field)
95
95
96type family ErrorUnless (field :: Symbol) (s :: Type) (contains :: Bool) :: Constraint where
96type family ErrorUnless (field :: Symbol) (s :: Type) (contains :: Bool) :: Constraint where
97 ErrorUnless field s 'False
97 ErrorUnless field s 'False