binrep-0.2.0: src/Binrep/Generic/CBLen.hs
{-# LANGUAGE UndecidableInstances #-}
{- | Generically derive 'CBLen' type family instances.
This is mostly playing around -- I've only just learned regular GHC generics,
and pulling everything up to the type level is even more confusing and weird.
A 'CBLen' instance usually indicates a type is either extremely simple or comes
with size information in the type. Be careful deriving or writing instances for
your own types - @BLen@ is usually correct/sufficient.
You can attempt to derive a 'CBLen' type family instance generically for a type
via
type instance CBLen a = CBLenGeneric w a
As with deriving @BLen@, you must provide the type used to store the sum tag for
sum types.
Then try doing something with it e.g. have GHC derive a @BLen@ instance for you
via the default method (that reifies CBLen)
deriving anyclass BLen a
Hopefully it either compiles, or you get a useful type error. If not, sorry.
-}
module Binrep.Generic.CBLen where
import Binrep.CBLen
import Binrep.Generic.Internal
import GHC.Generics
import GHC.TypeLits
import Data.Kind
import Data.Type.Equality
import Data.Type.Bool
type CBLenGeneric w a = GCBLen w (Rep a)
type family GCBLen w (f :: k -> Type) :: Natural where
GCBLen _ U1 = 0
GCBLen _ (K1 i c) = CBLen c
GCBLen w (l :*: r) = GCBLen w l + GCBLen w r
GCBLen w (l :+: r) = CBLen w + GCBLenCaseMaybe (GCBLenSum w (l :+: r))
GCBLen _ V1 = TypeError GErrRefuseVoid
GCBLen w (M1 _ _ f) = GCBLen w f
--type family GCBLenSum w (f :: k -> Type) :: Maybe Natural where
type family GCBLenSum w (f :: k -> Type) where
GCBLenSum w (C1 ('MetaCons name _ _) f) = JustX (GCBLen w f) name
GCBLenSum w (l :+: r) = MaybeEq (GCBLenSum w l) (GCBLenSum w r)
type family MaybeEq a b where
MaybeEq (JustX n nName) (JustX m _) = If (n == m) (JustX n nName) NothingX
MaybeEq _ _ = NothingX
-- | I don't know how to pattern match in types without writing type families.
type family GCBLenCaseMaybe a where
GCBLenCaseMaybe (JustX n _) = n
GCBLenCaseMaybe NothingX =
TypeError
( 'Text "Two constructors didn't have equal constant size."
':$$: 'Text "Sry dunno how to thread errors thru LOL"
)
-- TODO rewrite this stuff to thread error info through!
data JustX a b
data NothingX