@@ -0,0 +1,148 @@
1+{-# language AllowAmbiguousTypes #-}
2+{-# language DataKinds #-}
3+{-# language FlexibleInstances #-}
4+{-# language MultiParamTypeClasses #-}
5+{-# language PolyKinds #-}
6+{-# language ScopedTypeVariables #-}
7+{-# language StandaloneKindSignatures #-}
8+{-# language TypeApplications #-}
9+{-# language TypeFamilies #-}
10+{-# language TypeOperators #-}
11+{-# language UndecidableInstances #-}
13+module Rel8.Generic.Record
19+import Data.Kind ( Constraint, Type )
22+import Prelude hiding ( Show )
25+type Recordize :: (Type -> Type) -> Type -> Type
26+type family Recordize rep where
27+ Recordize (M1 D meta rep) = M1 D meta (Recordize rep)
28+ Recordize (l :+: r) = Recordize l :+: Recordize r
29+ Recordize (M1 C ('MetaCons name fixity 'False) rep) =
30+ M1 C ('MetaCons name fixity 'True) (Snd (Count 0 rep))
34+type Count :: Nat -> (Type -> Type) -> (Nat, Type -> Type)
35+type family Count n rep where
36+ Count n (M1 S ('MetaSel _selector su ss ds) rep) =
37+ '(n + 1, M1 S ('MetaSel ('Just (Show (n + 1))) su ss ds) rep)
38+ Count n (a :*: b) = CountHelper1 (Count n a) b
39+ Count n rep = '(n, rep)
42+type CountHelper1 :: (Nat, Type -> Type) -> (Type -> Type) -> (Nat, Type -> Type)
43+type family CountHelper1 tuple b where
44+ CountHelper1 '(n, a) b = CountHelper2 a (Count n b)
47+type CountHelper2 :: (Type -> Type) -> (Nat, Type -> Type) -> (Nat, Type -> Type)
48+type family CountHelper2 a tuple where
49+ CountHelper2 a '(n, b) = '(n, a :*: b)
52+type Show :: Nat -> Symbol
54+ AppendSymbol "_" (AppendSymbol (Show' (Div n 10)) (ShowDigit (Mod n 10)))
57+type Show' :: Nat -> Symbol
58+type family Show' n where
60+ Show' n = AppendSymbol (Show' (Div n 10)) (ShowDigit (Mod n 10))
63+type ShowDigit :: Nat -> Symbol
64+type family ShowDigit n where
77+type Snd :: (a, b) -> b
78+type family Snd tuple where
82+type Recordizable :: (Type -> Type) -> Constraint
83+class Recordizable rep where
84+ recordize :: rep x -> Recordize rep x
85+ unrecordize :: Recordize rep x -> rep x
88+instance Recordizable rep => Recordizable (M1 D meta rep) where
89+ recordize (M1 a) = M1 (recordize a)
90+ unrecordize (M1 a) = M1 (unrecordize a)
93+instance (Recordizable l, Recordizable r) => Recordizable (l :+: r) where
94+ recordize (L1 a) = L1 (recordize a)
95+ recordize (R1 a) = R1 (recordize a)
96+ unrecordize (L1 a) = L1 (unrecordize a)
97+ unrecordize (R1 a) = R1 (unrecordize a)
100+instance Countable 0 rep =>
101+ Recordizable (M1 C ('MetaCons name fixity 'False) rep)
103+ recordize (M1 a) = M1 (count @0 a)
104+ unrecordize (M1 a) = M1 (uncount @0 a)
107+instance {-# OVERLAPPABLE #-} Recordize rep ~ rep => Recordizable rep where
112+type Countable :: Nat -> (Type -> Type) -> Constraint
113+class Countable n rep where
114+ count :: rep x -> Snd (Count n rep) x
115+ uncount :: Snd (Count n rep) x -> rep x
118+instance Countable n (M1 S ('MetaSel selector su ss ds) rep) where
120+ uncount (M1 a) = M1 a
124+ ( Countable n a, Countable n' b
125+ , '(n', a') ~ Count n a
126+ , Snd (CountHelper2 a' (Count n' b)) ~ (a' :*: Snd (Count n' b))
128+ => Countable n (a :*: b)
130+ count (a :*: b) = count @n a :*: count @n' b
131+ uncount (a :*: b) = uncount @n a :*: uncount @n' b
134+instance {-# OVERLAPPABLE #-} Snd (Count n rep) ~ rep => Countable n rep where
139+newtype Record a = Record
144+instance (Generic a, Recordizable (Rep a)) => Generic (Record a) where
145+ type Rep (Record a) = Recordize (Rep a)
147+ from (Record a) = recordize (from a)
148+ to = Record . to . unrecordize