{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE Unsafe #-}
module Generics.Linear.Unsafe.ViaGHCGenerics
( GHCGenerically(..)
, GHCGenerically1(..)
) where
import Data.Coerce (Coercible, coerce)
import Data.Kind (Constraint, Type)
import Data.Type.Bool (type (&&))
import Generics.Linear
import qualified GHC.Generics as G
import Unsafe.Coerce
import GHC.Exts (Any)
import GHC.TypeLits (TypeError, ErrorMessage (..))
newtype GHCGenerically a = GHCGenerically { forall a. GHCGenerically a -> a
unGHCGenerically :: a }
instance G.Generic a => Generic (GHCGenerically a) where
type Rep (GHCGenerically a) = G.Rep a
to :: forall p (m :: Multiplicity).
Rep (GHCGenerically a) p %m -> GHCGenerically a
to = forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %1 -> a %q -> b
toLinear (forall a. a -> GHCGenerically a
GHCGenerically forall b c (p :: * -> * -> *) a.
Coercible b c =>
p b c -> (a -> b) -> a -> c
#. forall a x. Generic a => Rep a x -> a
G.to)
from :: forall p (m :: Multiplicity).
GHCGenerically a %m -> Rep (GHCGenerically a) p
from = forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %1 -> a %q -> b
toLinear (forall a x. Generic a => a -> Rep a x
G.from forall a b c (p :: * -> * -> *).
Coercible a b =>
(b -> c) -> p a b -> a -> c
.# forall a. GHCGenerically a -> a
unGHCGenerically)
toLinear
:: forall a b p q.
(a %p-> b) %1-> (a %q-> b)
toLinear :: forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %1 -> a %q -> b
toLinear a %p -> b
f = case forall {k} (a :: k) (b :: k). UnsafeEquality a b
unsafeEqualityProof @p @q of
UnsafeEquality p q
UnsafeRefl -> a %p -> b
f
infixr 9 #.
(#.) :: Coercible b c => p b c -> (a -> b) -> a -> c
#. :: forall b c (p :: * -> * -> *) a.
Coercible b c =>
p b c -> (a -> b) -> a -> c
(#.) p b c
_ = coerce :: forall a b. Coercible a b => a -> b
coerce
infixl 8 .#
(.#) :: Coercible a b => (b -> c) -> p a b -> a -> c
b -> c
f .# :: forall a b c (p :: * -> * -> *).
Coercible a b =>
(b -> c) -> p a b -> a -> c
.# p a b
_ = coerce :: forall a b. Coercible a b => a -> b
coerce b -> c
f
type GHCGenerically1 :: forall k. (k -> Type) -> k -> Type
newtype GHCGenerically1 f a = GHCGenerically1 { forall k (f :: k -> *) (a :: k). GHCGenerically1 f a -> f a
unGHCGenerically1 :: f a }
instance forall k (f :: k -> Type).
( forall (a :: k). G.Generic (f a)
, CheckValid f
) => Generic1 (GHCGenerically1 f) where
type Rep1 (GHCGenerically1 (f :: k -> Type)) = MakeRep1 @k (MarkedRep f)
to1 :: forall a m. Rep1 (GHCGenerically1 f) a %m-> GHCGenerically1 f a
to1 :: forall (p :: k) (m :: Multiplicity).
Rep1 (GHCGenerically1 f) p %m -> GHCGenerically1 f p
to1 = forall a b. a -> b
unsafeCoerce (forall a x. Generic a => Rep a x -> a
G.to :: G.Rep (f a) Any -> f a)
from1 :: forall a m. GHCGenerically1 f a %m-> Rep1 (GHCGenerically1 f) a
from1 :: forall (p :: k) (m :: Multiplicity).
GHCGenerically1 f p %m -> Rep1 (GHCGenerically1 f) p
from1 = forall a b. a -> b
unsafeCoerce (forall a x. Generic a => a -> Rep a x
G.from :: f a -> G.Rep (f a) Any)
data LastMarkT = LastMark
data OtherMarkT = OtherMark
type family LastPar :: LastMarkT -> k
type family OtherPar :: OtherMarkT -> k -> k
type CheckValid :: forall k. (k -> Type) -> Constraint
type CheckValid (f :: k -> Type) = CheckValid' f (ValidRep1 (MarkedRep f))
type MarkedRep :: forall k. (k -> Type) -> Type -> Type
type MarkedRep (f :: k -> Type) = G.Rep ((MarkOtherPars f) (LastPar 'LastMark :: k))
type CheckValid' :: forall k. (k -> Type) -> Bool -> Constraint
type family CheckValid' f valid where
CheckValid' _ 'True = ()
CheckValid' f 'False = TypeError
('Text "Cannot create Generic1 instance for" ':$$:
'ShowType f ':$$:
'Text "the last parameter appears in an invalid location.")
type MakeRep1 :: forall k. (Type -> Type) -> k -> Type
type family MakeRep1 (rep :: Type -> Type) :: k -> Type where
MakeRep1 (M1 i c f) = M1 i c (MakeRep1 f)
MakeRep1 (x :+: y) = MakeRep1 x :+: MakeRep1 y
MakeRep1 (x :*: y) = MakeRep1 x :*: MakeRep1 y
MakeRep1 U1 = U1
MakeRep1 V1 = V1
MakeRep1 (Rec0 c) = MakeRep1Field (Rec0 (Unmark c)) Par1 c
type ValidRep1 :: (Type -> Type) -> Bool
type family ValidRep1 rep where
ValidRep1 (M1 _ _ f) = ValidRep1 f
ValidRep1 (x :+: y) = ValidRep1 x && ValidRep1 y
ValidRep1 (x :*: y) = ValidRep1 x && ValidRep1 y
ValidRep1 U1 = 'True
ValidRep1 V1 = 'True
ValidRep1 (Rec0 c) = ValidRep1Field c
type MarkOtherPars :: forall k. k -> k
type family MarkOtherPars (f :: k) :: k where
MarkOtherPars ((f :: j -> k) (a :: j)) = MarkOtherPars f (OtherPar 'OtherMark a)
MarkOtherPars f = f
type Unmark :: forall k. k -> k
type family Unmark f where
Unmark (_LastPar 'LastMark) = Stuck
Unmark (_OtherPar 'OtherMark a) = a
Unmark ((f :: j -> k) (a :: j)) = Unmark f (Unmark a)
Unmark a = a
type Stuck :: forall k. k
type family Stuck where
type NoLast :: forall k. k -> Bool
type family NoLast f where
NoLast (_LastPar 'LastMark) = 'False
NoLast (_OtherPar 'OtherMark a) = 'True
NoLast ((f :: j -> k) (a :: j)) = NoLast f && NoLast a
NoLast _ = 'True
type MakeRep1Field :: forall j k. (k -> Type) -> (j -> Type) -> j -> k -> Type
type family MakeRep1Field fk acc c where
MakeRep1Field fk (acc :: k -> Type) (_LastPar 'LastMark :: k) = acc
MakeRep1Field fk (_ :: b -> Type) (_OtherPar 'OtherMark _) = fk
MakeRep1Field fk (acc :: b -> Type) ((f :: a -> b) (x :: a)) = MakeRep1Field fk (acc :.: Unmark f) x
MakeRep1Field fk _ _ = fk
type ValidRep1Field :: forall k. k -> Bool
type family ValidRep1Field c where
ValidRep1Field (_LastPar 'LastMark :: k) = 'True
ValidRep1Field (_OtherPar 'OtherMark _) = 'True
ValidRep1Field ((f :: a -> b) (x :: a)) = NoLast f && ValidRep1Field x
ValidRep1Field _ = 'True