record-encode-0.1.0.0: src/Data/Record/Encode/Generics.hs
{-# language TypeOperators #-}
{-# language DeriveGeneric #-}
-- {-# language GADTs, DataKinds, PolyKinds, FlexibleInstances, FlexibleContexts #-}
{-# language KindSignatures, FlexibleInstances, FlexibleContexts, ScopedTypeVariables #-}
module Data.Record.Encode.Generics (
gindex
, GVariants(..)
, gnconstructors
) where
import qualified GHC.Generics as G
import Data.Proxy
import Generics.SOP hiding (Proxy)
import Generics.SOP.NS
data X a = A | B a | C | D | E | F deriving G.Generic
instance Generic (X a)
-- | Compute the structural index of a value of a sum type via its Generic representation
-- e.g.:
--
-- >>> data S = Sa | Sb | Sc deriving (Eq, Show, G.Generic)
-- >>> instance Generic S
--
-- >>> gindex $ from Sb
-- 1
gindex :: SOP f xs -> Int
gindex = index_SOP
-- | Counts the number of outermost constructors ("variants" of a type)
class GVariants (f :: * -> *) where
vars :: proxy f -> Int
instance GVariants (G.M1 G.C m f) where { vars _ = 1 }
instance GVariants G.V1 where { vars _ = 0 }
instance GVariants f => GVariants (G.M1 G.D m f) where { vars _ = vars (Proxy :: Proxy f) }
instance (GVariants f, GVariants g) => GVariants (f G.:+: g) where { vars _ = vars (Proxy :: Proxy f) + vars (Proxy :: Proxy g) }
-- | Counts the number of outermost constructors
gnconstructors :: forall a . (G.Generic a, GVariants (G.Rep a)) => Proxy a -> Int
gnconstructors _ = vars (Proxy :: Proxy (G.Rep a))
-- [17:21] <mniip> @let class Variants f where { variants :: proxy f -> Int }; instance Variants (M1 C m f) where { variants _ = 1 }; instance Variants V1 where { variants _ = 0 }; instance Variants f => Variants (M1 D m f) where { variants _ = variants (Proxy :: Proxy f) }; instance (Variants f, Variants g) => Variants (f :+: g) where { variants _ = variants (Proxy :: Proxy f) + variants (Proxy :: Proxy g) }
-- [17:21] <lambdabot> Defined.
-- [17:21] <mniip> @let variants' :: forall a. (Generic a, Variants (Rep a)) => Proxy a -> Int; variants' _ = variants (Proxy :: Proxy (Rep a))
-- [17:21] <lambdabot> Defined.
-- [17:21] <mniip> > variants' (Proxy :: Proxy Bool)
-- [17:21] <lambdabot> 2
-- [17:22] <mniip> > variants' (Proxy :: Proxy (Maybe (Either Bool Bool)))
-- [17:22] <lambdabot> 2
-- [17:22] <mniip> as you can see this only focuses on the outer type constructor
-- [17:22] <mniip> > variants (Proxy :: Proxy Proxy)
-- -- |
-- class GEncode i o where
-- gencode :: i x -> Maybe (o x)
-- -- λ> :t fmap to . gencode . from
-- --
-- -- fmap to . gencode . from
-- -- :: (GEncode (Rep a) (Rep b), Generic b, Generic a) =>
-- -- a -> Maybe b
-- -- instance GEncode (V1 p) where
-- -- gencode _ = error "Cannot encode V1"
-- -- instance GEncode (U1 p) where
-- -- gencode U1 = error "Cannot encode U1"
-- data OneHot = OH !Int !Int deriving (Eq, Show)
-- class Encode d where
-- type ETy d :: *
-- type ETy d = OneHot -- (Int, Int)
-- -- encode :: d -> V.Vector (ETy d)
-- encode :: d x -> ETy d
-- -- instance Encode
-- instance Encode (V1 p) where
-- encode _ = error "Cannot encode V1"
-- instance Encode (U1 p) where
-- encode U1 = error "Cannot encode U1"
-- instance Encode (K1 i c p) where
-- instance Encode (M1 i c f p) where
-- instance Encode ((f :*: g) p) where
-- instance Encode ((f :+: g) p) where
-- class VG.Vector v x => GEncode' i v x where
-- gencode' :: i x -> Maybe (v Int)