@@ -0,0 +1,116 @@
13+import Control.Monad.Reader as X
15+import GHC.Generics as G
21+instance {-# OVERLAPS #-} Has r r where
24+type family HasAll (xs :: [*]) r :: Constraint where
26+ HasAll (x ': xs) r = (Has x r, HasAll xs r)
28+data LensList (r :: *) (es :: [*]) where
29+ LLNil :: LensList r '[]
30+ LLCons :: Lens r r e e -> LensList r es -> LensList r (e ': es)
32+mapLL :: Lens s s r r -> LensList r es -> LensList s es
34+mapLL m (LLCons l ls) = LLCons (m . l) (mapLL m ls)
36+type family (xs :: [*]) ++ (ys :: [*]) :: [*] where
38+ (x ': xs) ++ ys = x ': (xs ++ ys)
40+concatLL :: LensList r es1 -> LensList r es2 -> LensList r (es1 ++ es2)
41+concatLL LLNil ys = ys
42+concatLL (LLCons l ls) ys = LLCons l (concatLL ls ys)
44+-- borrowed from Data.HSet.Get
47+type family IndexOf (x :: *) (xs :: [*]) :: N where
48+ IndexOf x (x ': _) = 'Z
49+ IndexOf x (_ ': xs) = 'S (IndexOf x xs)
51+class (i ~ IndexOf e es) => GetLens e es i | i es -> e where
52+ getLens :: LensList r es -> Lens r r e e
54+type Elem e es = GetLens e es (IndexOf e es)
56+class Fieldy (r :: *) where
58+ type Fields r = GFields (Rep r)
59+ lensList :: LensList r (Fields r)
61+ :: (Generic r, GFieldy (Rep r), Fields r ~ (GFields (Rep r)))
62+ => LensList r (Fields r)
63+ lensList = mapLL (iso G.from G.to) glensList
65+instance {-# OVERLAPPABLE #-} (Fieldy r, Elem e (Fields r)) => Has e r where
66+ part = getLens lensList
68+class (MonadReader r m, HasAll es r)
69+ => MonadHas (es :: [*]) (r :: *) (m :: * -> *) | m -> r
70+instance (MonadReader r m, HasAll es r) => MonadHas es r m
72+instance GetLens e (e ': es) 'Z where
73+ getLens (LLCons l _) = l
75+instance (GetLens e' es n, 'S n ~ IndexOf e' (e ': es))
76+ => GetLens e' (e ': es) ('S n) where
77+ getLens (LLCons _ ls) = getLens ls
79+class GFieldy (r :: * -> *) where
80+ type GFields r :: [*]
81+ glensList :: LensList (r x) (GFields r)
83+instance GFieldyProduct r => GFieldy (D1 d (C1 c r)) where
84+ type GFields (D1 d (C1 c r)) = GFieldsProduct r
85+ glensList = mapLL (iso unM1 M1 . iso unM1 M1) glensListProduct
87+class GFieldyProduct (r :: * -> *) where
88+ type GFieldsProduct r :: [*]
89+ glensListProduct :: LensList (r x) (GFieldsProduct r)
91+instance (GFieldyProduct r, GFieldyProduct s) => GFieldyProduct (r :*: s) where
92+ type GFieldsProduct (r :*: s) = GFieldsProduct r ++ GFieldsProduct s
95+ (mapLL (lens lget lset) glensListProduct)
96+ (mapLL (lens rget rset) glensListProduct)
99+ lset (_ :*: r) l = l :*: r
101+ rset (l :*: _) r = l :*: r
103+instance GFieldyProduct (S1 s (K1 k r)) where
104+ type GFieldsProduct (S1 s (K1 k r)) = '[r]
105+ glensListProduct = LLCons (iso unM1 M1 . iso unK1 K1) LLNil
107+type family AllElem (xs :: [*]) (es :: [*]) :: Constraint where
109+ AllElem (x ': xs) es = (Elem x es, AllElem xs es)
111+instance Fieldy (a, b)
112+instance Fieldy (a, b, c)
113+instance Fieldy (a, b, c, d)
114+instance Fieldy (a, b, c, d, e)
115+instance Fieldy (a, b, c, d, e, f)
116+instance Fieldy (a, b, c, d, e, f, g)