barbies-1.0.0.0: src/Data/Generics/GenericN.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
--------------------------------------------------------------------------------
-- |
-- Module : Data.Generics.GenericN
-- Copyright : (C) 2018 Csongor Kiss
-- License : BSD3
-- Stability : experimental
-- Portability : non-portable
--
-- Generic representation of types with multiple parameters
--
--------------------------------------------------------------------------------
module Data.Generics.GenericN
( Param
, SameOrParam
, Rec (Rec, unRec)
, GenericN (..)
, module GHC.Generics
) where
import Data.Kind
import GHC.Generics
import GHC.TypeLits
import Data.Coerce
data Param (n :: Nat) (original :: k' -> k'') (a :: k)
type family Indexed (t :: k) (i :: Nat) :: k where
Indexed (t a) i = Indexed t (i + 1) (Param i a)
Indexed t _ = t
newtype Rec (p :: Type) a x = Rec { unRec :: K1 R a x }
type family Zip (a :: Type -> Type) (b :: Type -> Type) :: Type -> Type where
Zip (M1 mt m s) (M1 mt m t)
= M1 mt m (Zip s t)
Zip (l :+: r) (l' :+: r')
= Zip l l' :+: Zip r r'
Zip (l :*: r) (l' :*: r')
= Zip l l' :*: Zip r r'
Zip (Rec0 p) (Rec0 a)
= Rec p a
Zip U1 U1
= U1
Zip V1 V1
= V1
class
( Coercible (Rep a) (RepN a)
, Generic a
) => GenericN (a :: Type) where
type family RepN (a :: Type) :: Type -> Type
type instance RepN a = Zip (Rep (Indexed a 0)) (Rep a)
toN :: RepN a x -> a
fromN :: a -> RepN a x
instance
( Coercible (Rep a) (RepN a)
, Generic a
) => GenericN a where
toN :: forall x. RepN a x -> a
toN = coerce (to :: Rep a x -> a)
{-# INLINE toN #-}
fromN :: forall x. a -> RepN a x
fromN = coerce (from :: a -> Rep a x)
{-# INLINE fromN #-}
-- | @'SameOrParam' a b@ holds iff @a ~ b@ or @'Param' n a ~ b@.
-- It is useful when defining generic instances and one don't
-- want to differentiate the case of a parameter-usage from
-- the usage of a constant.
class SameOrParam (a :: k) (b :: k)
instance SameOrParam a a
instance SameOrParam (Param n a) a
instance SameOrParam a (Param n a)