{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Generics.Simplistic
(
Generic, Rep, Rep1, Par1, Rec1, (:.:)(..), V1, U1(..), (:+:)(..)
, (:*:)(..), K1(..), M1(..), (:=>:)(..), R
, GMeta(..), SMeta(..), SMetaI(..), SRep(..) , I(..) , Simplistic
, OnLeaves
, repMap , repMapM , repMapCM
, zipSRep , repLeaves , repLeavesC , repLeavesList
, getDatatypeName , getConstructorName
, repDatatypeName , repConstructorName
, fromS , toS , GShallow(..)
, SRep1(..) , OnLeaves1 , fromS1 , toS1 , GShallow1(..) , Simplistic1
, Implies, Trivial
) where
import Data.Proxy
import Control.Monad.Identity
import Control.DeepSeq
import GHC.Generics
import GHC.Generics.Extra
import GHC.Exts (Constraint)
import Generics.Simplistic.Util
data SMeta i t where
SM_D :: Datatype d => SMeta D d
SM_C :: Constructor c => SMeta C c
SM_S :: Selector s => SMeta S s
deriving instance Show (SMeta i t)
deriving instance Eq (SMeta i t)
data SMetaI d f x = SMetaI
smetaI :: SMeta i t -> SMetaI t Proxy ()
smetaI _ = SMetaI
getDatatypeName :: SMeta D d -> String
getDatatypeName x@SM_D = datatypeName (smetaI x)
getConstructorName :: SMeta C c -> String
getConstructorName x@SM_C = conName (smetaI x)
class GMeta i c where
smeta :: SMeta i c
instance Constructor c => GMeta C c where
smeta = SM_C
instance Datatype d => GMeta D d where
smeta = SM_D
instance Selector s => GMeta S s where
smeta = SM_S
infixr 5 :**:
data SRep w f where
S_U1 :: SRep w U1
S_L1 :: SRep w f -> SRep w (f :+: g)
S_R1 :: SRep w g -> SRep w (f :+: g)
(:**:) :: SRep w f -> SRep w g -> SRep w (f :*: g)
S_K1 :: w a -> SRep w (K1 i a)
S_M1 :: SMeta i t -> SRep w f -> SRep w (M1 i t f)
S_ST :: c => SRep w f -> SRep w (c :=>: f)
deriving instance (forall a. Show (w a)) => Show (SRep w f)
deriving instance (forall a. Eq (w a)) => Eq (SRep w f)
instance (forall x . NFData (w x)) => NFData (SRep w f) where
rnf S_U1 = ()
rnf (S_K1 w) = rnf w
rnf (S_M1 _ x) = rnf x
rnf (S_L1 x) = rnf x
rnf (S_R1 x) = rnf x
rnf (x :**: y) = rnf x `seq` rnf y
rnf (S_ST x) = rnf x
type Simplistic a = (Generic a , GShallow (Rep a))
type family OnLeaves (c :: * -> Constraint) (f :: * -> *) :: Constraint where
OnLeaves c V1 = ()
OnLeaves c U1 = ()
OnLeaves c (f :+: g) = (OnLeaves c f, OnLeaves c g)
OnLeaves c (f :*: g) = (OnLeaves c f, OnLeaves c g)
OnLeaves c (K1 i a) = c a
OnLeaves c (M1 i p f) = OnLeaves c f
OnLeaves c (d :=>: f) = Implies d (OnLeaves c f)
repDatatypeName :: SRep w f -> String
repDatatypeName (S_M1 x@SM_D _)
= getDatatypeName x
repDatatypeName (S_M1 _ x)
= repDatatypeName x
repDatatypeName (S_L1 x)
= repDatatypeName x
repDatatypeName (S_R1 x)
= repDatatypeName x
repDatatypeName _
= error "Please; use GHC's deriving mechanism. This keeps M1's at the top of the Rep"
repConstructorName :: SRep w f -> String
repConstructorName (S_M1 x@SM_C _)
= getConstructorName x
repConstructorName (S_M1 _ x)
= repConstructorName x
repConstructorName (S_L1 x)
= repConstructorName x
repConstructorName (S_R1 x)
= repConstructorName x
repConstructorName _
= error "Please; use GHC's deriving mechanism. This keeps M1's at the top of the Rep"
zipSRep :: SRep w f -> SRep z f -> Maybe (SRep (w :*: z) f)
zipSRep S_U1 S_U1 = return S_U1
zipSRep (S_L1 x) (S_L1 y) = S_L1 <$> zipSRep x y
zipSRep (S_R1 x) (S_R1 y) = S_R1 <$> zipSRep x y
zipSRep (S_M1 m x) (S_M1 _ y) = S_M1 m <$> zipSRep x y
zipSRep (x1 :**: x2) (y1 :**: y2) = (:**:) <$> (zipSRep x1 y1) <*> (zipSRep x2 y2)
zipSRep (S_K1 x) (S_K1 y) = return $ S_K1 (x :*: y)
zipSRep _ _ = Nothing
repLeavesC :: (OnLeaves c rep)
=> Proxy c
-> (forall x . c x => w x -> r)
-> (r -> r -> r)
-> r
-> SRep w rep -> r
repLeavesC _ _ _ e S_U1 = e
repLeavesC p l j e (S_L1 x) = repLeavesC p l j e x
repLeavesC p l j e (S_R1 x) = repLeavesC p l j e x
repLeavesC p l j e (S_M1 _ x) = repLeavesC p l j e x
repLeavesC p l j e (x :**: y) = j (repLeavesC p l j e x) (repLeavesC p l j e y)
repLeavesC _ l _ _ (S_K1 x) = l x
repLeavesC p l j e (S_ST x) = repLeavesC p l j e x
repLeaves :: (forall x . w x -> r)
-> (r -> r -> r)
-> r
-> SRep w rep -> r
repLeaves _ _ e S_U1 = e
repLeaves l j e (S_L1 x) = repLeaves l j e x
repLeaves l j e (S_R1 x) = repLeaves l j e x
repLeaves l j e (S_M1 _ x) = repLeaves l j e x
repLeaves l j e (x :**: y) = j (repLeaves l j e x) (repLeaves l j e y)
repLeaves l _ _ (S_K1 x) = l x
repLeaves l j e (S_ST x) = repLeaves l j e x
repLeavesList :: SRep w rep -> [Exists w]
repLeavesList = repLeaves ((:[]) . Exists) (++) []
repMapCM :: (Monad m , OnLeaves c rep)
=> Proxy c
-> (forall y . c y => f y -> m (g y))
-> SRep f rep -> m (SRep g rep)
repMapCM _p _f (S_U1) = return S_U1
repMapCM _p f (S_K1 x) = S_K1 <$> f x
repMapCM p f (S_M1 m x) = S_M1 m <$> repMapCM p f x
repMapCM p f (S_L1 x) = S_L1 <$> repMapCM p f x
repMapCM p f (S_R1 x) = S_R1 <$> repMapCM p f x
repMapCM p f (x :**: y) = (:**:) <$> repMapCM p f x <*> repMapCM p f y
repMapCM p f (S_ST x) = S_ST <$> repMapCM p f x
repMapM :: (Monad m)
=> (forall y . f y -> m (g y))
-> SRep f rep -> m (SRep g rep)
repMapM _f (S_U1) = return S_U1
repMapM f (S_K1 x) = S_K1 <$> f x
repMapM f (S_M1 m x) = S_M1 m <$> repMapM f x
repMapM f (S_L1 x) = S_L1 <$> repMapM f x
repMapM f (S_R1 x) = S_R1 <$> repMapM f x
repMapM f (S_ST x) = S_ST <$> repMapM f x
repMapM f (x :**: y)
= (:**:) <$> repMapM f x <*> repMapM f y
repMap :: (forall y . f y -> g y)
-> SRep f rep -> SRep g rep
repMap f = runIdentity . repMapM (return . f)
newtype I x = I { unI :: x }
deriving Eq
instance Show x => Show (I x) where
showsPrec p (I x) = showParen (p > 10) $ showString "I " . showsPrec 11 x
instance Functor I where
fmap f (I x) = I (f x)
instance Applicative I where
pure = I
I f <*> I x = I (f x)
instance Monad I where
I x >>= f = f x
class GShallow f where
sfrom :: f x -> SRep I f
sto :: SRep I f -> f x
instance GShallow U1 where
sfrom U1 = S_U1
sto S_U1 = U1
instance (GShallow f , GShallow g) => GShallow (f :+: g) where
sfrom (L1 x) = S_L1 (sfrom x)
sfrom (R1 x) = S_R1 (sfrom x)
sto (S_L1 x) = L1 (sto x)
sto (S_R1 x) = R1 (sto x)
instance (GShallow f , GShallow g) => GShallow (f :*: g) where
sfrom (x :*: y) = sfrom x :**: sfrom y
sto (x :**: y) = sto x :*: sto y
instance (GShallow f , GMeta i c) => GShallow (M1 i c f) where
sfrom (M1 x) = S_M1 smeta (sfrom x)
sto (S_M1 _ x) = M1 (sto x)
instance GShallow (K1 R x) where
sfrom (K1 x) = S_K1 (I x)
sto (S_K1 (I x)) = K1 x
fromS :: (Simplistic a) => a -> SRep I (Rep a)
fromS = sfrom . from
toS :: (Simplistic a) => SRep I (Rep a) -> a
toS = to . sto
infixr 5 :***:
data SRep1 f x where
S1_U1 :: SRep1 U1 x
S1_L1 :: SRep1 f x -> SRep1 (f :+: g) x
S1_R1 :: SRep1 g x -> SRep1 (f :+: g) x
(:***:) :: SRep1 f x -> SRep1 g x -> SRep1 (f :*: g) x
S1_K1 :: a -> SRep1 (K1 i a) x
S1_M1 :: SMeta i t -> SRep1 f x -> SRep1 (M1 i t f) x
S1_ST :: c => SRep1 f x -> SRep1 (c :=>: f) x
S1_Par :: x -> SRep1 Par1 x
S1_Rec :: f x -> SRep1 (Rec1 f) x
S1_Comp :: f (SRep1 g x) -> SRep1 (f :.: g) x
type Simplistic1 f = (Generic1 f, GShallow1 (Rep1 f))
type family OnLeaves1 (c :: * -> Constraint) (r :: (* -> *) -> Constraint)
(f :: * -> *) :: Constraint where
OnLeaves1 c r V1 = ()
OnLeaves1 c r U1 = ()
OnLeaves1 c r (f :+: g) = (OnLeaves1 c r f, OnLeaves1 c r g)
OnLeaves1 c r (f :*: g) = (OnLeaves1 c r f, OnLeaves1 c r g)
OnLeaves1 c r (K1 i a) = c a
OnLeaves1 c r (M1 i p f) = OnLeaves1 c r f
OnLeaves1 c r (d :=>: f) = Implies d (OnLeaves1 c r f)
OnLeaves1 c r Par1 = ()
OnLeaves1 c r (Rec1 f) = r f
OnLeaves1 c r (f :.: g) = (r f, OnLeaves1 c r g)
fromS1 :: (Simplistic1 f) => f x -> SRep1 (Rep1 f) x
fromS1 = sfrom1 . from1
toS1 :: (Simplistic1 f) => SRep1 (Rep1 f) x -> f x
toS1 = to1 . sto1
class GShallow1 f where
sfrom1 :: f a -> SRep1 f a
sto1 :: SRep1 f a -> f a
instance GShallow1 V1 where
sfrom1 = undefined
sto1 = undefined
instance GShallow1 U1 where
sfrom1 U1 = S1_U1
sto1 S1_U1 = U1
instance (GShallow1 f, GShallow1 g) => GShallow1 (f :+: g) where
sfrom1 (L1 x) = S1_L1 (sfrom1 x)
sfrom1 (R1 y) = S1_R1 (sfrom1 y)
sto1 (S1_L1 x) = L1 (sto1 x)
sto1 (S1_R1 y) = R1 (sto1 y)
instance (GShallow1 f, GShallow1 g) => GShallow1 (f :*: g) where
sfrom1 (x :*: y) = sfrom1 x :***: sfrom1 y
sto1 (x :***: y) = sto1 x :*: sto1 y
instance GShallow1 (K1 i a) where
sfrom1 (K1 x) = S1_K1 x
sto1 (S1_K1 x) = K1 x
instance (GMeta i t, GShallow1 f) => GShallow1 (M1 i t f) where
sfrom1 (M1 x) = S1_M1 smeta (sfrom1 x)
sto1 (S1_M1 _ x) = M1 (sto1 x)
instance (c => GShallow1 f) => GShallow1 (c :=>: f) where
sfrom1 (SuchThat x) = S1_ST (sfrom1 x)
sto1 (S1_ST x) = SuchThat (sto1 x)
instance GShallow1 Par1 where
sfrom1 (Par1 x) = S1_Par x
sto1 (S1_Par x) = Par1 x
instance GShallow1 (Rec1 f) where
sfrom1 (Rec1 x) = S1_Rec x
sto1 (S1_Rec x) = Rec1 x
instance (Functor f, GShallow1 g) => GShallow1 (f :.: g) where
sfrom1 (Comp1 x) = S1_Comp (fmap sfrom1 x)
sto1 (S1_Comp x) = Comp1 (fmap sto1 x)