----------------------------------------------------------------------------- -- | -- Module : Generics.OneLiner.Internal.Unary -- License : BSD-style (see the file LICENSE) -- -- Maintainer : sjoerd@w3future.com -- Stability : experimental -- Portability : non-portable -- ----------------------------------------------------------------------------- {-# LANGUAGE PolyKinds , RankNTypes , LinearTypes , TypeFamilies , ConstraintKinds , FlexibleContexts , TypeApplications , FlexibleInstances , AllowAmbiguousTypes , ScopedTypeVariables , MultiParamTypeClasses , UndecidableSuperClasses #-} module Generics.OneLiner.Internal.Unary where import Data.Kind (Constraint) import Generics.OneLiner.Classes import qualified Generics.OneLiner.Internal as I -- | Type-level 'join', of kind @(k -> k -> k') -> k -> k'@. type J f a = f a a -- | Constraint-level 'duplicate', of kind @(k -> Constraint) -> k -> k -> Constraint@. class (c a, a ~ b) => D (c :: k -> Constraint) a b instance (c a, a ~ b) => D c a b type Constraints t c = I.Constraints t t (D c) type Constraints1 t c = I.Constraints1 t t (D c) type Constraints01 t c0 c1 = I.Constraints01 t t (D c0) (D c1) type Constraints' t c c1 = I.Constraints' t t (D c) (D c1) type ADTRecord t = (I.ADTRecord t t, Constraints t AnyType) type ADTRecord1 t = (I.ADTRecord1 t t, Constraints1 t AnyType) type ADTNonEmpty t = (I.ADTNonEmpty t t, Constraints t AnyType) type ADTNonEmpty1 t = (I.ADTNonEmpty1 t t, Constraints1 t AnyType) type ADT t = (I.ADT t t, Constraints t AnyType) type ADT1 t = (I.ADT1 t t, Constraints1 t AnyType) record :: forall c p t. (ADTRecord t, Constraints t c, GenericRecordProfunctor p) => (forall s. c s => p s s) -> p t t record p = I.record @(D c) p {-# INLINE record #-} record1 :: forall c p t a b. (ADTRecord1 t, Constraints1 t c, GenericRecordProfunctor p) => (forall d e s. c s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) record1 f = I.record1 @(D c) f {-# INLINE record1 #-} record01 :: forall c0 c1 p t a b. (ADTRecord1 t, Constraints01 t c0 c1, GenericRecordProfunctor p) => (forall s. c0 s => p s s) -> (forall d e s. c1 s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) record01 f g = I.record01 @(D c0) @(D c1) f g {-# INLINE record01 #-} nonEmpty :: forall c p t. (ADTNonEmpty t, Constraints t c, GenericNonEmptyProfunctor p) => (forall s. c s => p s s) -> p t t nonEmpty p = I.nonEmpty @(D c) p {-# INLINE nonEmpty #-} nonEmpty1 :: forall c p t a b. (ADTNonEmpty1 t, Constraints1 t c, GenericNonEmptyProfunctor p) => (forall d e s. c s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) nonEmpty1 f = I.nonEmpty1 @(D c) f {-# INLINE nonEmpty1 #-} nonEmpty01 :: forall c0 c1 p t a b. (ADTNonEmpty1 t, Constraints01 t c0 c1, GenericNonEmptyProfunctor p) => (forall s. c0 s => p s s) -> (forall d e s. c1 s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) nonEmpty01 f g = I.nonEmpty01 @(D c0) @(D c1) f g {-# INLINE nonEmpty01 #-} generic :: forall c p t. (ADT t, Constraints t c, GenericProfunctor p) => (forall s. c s => p s s) -> p t t generic p = I.generic @(D c) @p @t @t p {-# INLINE generic #-} generic1 :: forall c p t a b. (ADT1 t, Constraints1 t c, Generic1Profunctor p) => (forall d e s. c s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) generic1 f = I.generic1 @(D c) @p @t @t f {-# INLINE generic1 #-} generic01 :: forall c0 c1 p t a b. (ADT1 t, Constraints01 t c0 c1, GenericProfunctor p) => (forall s. c0 s => p s s) -> (forall d e s. c1 s => p d e -> p (s d) (s e)) -> p a b -> p (t a) (t b) generic01 f g = I.generic01 @(D c0) @(D c1) f g {-# INLINE generic01 #-} -- | Get the index in the lists returned by `create` and `createA` of the constructor of the given value. -- -- For example, this is the implementation of `put` that generates the binary data that -- the above implentation of `get` expects: -- -- @ -- `put` t = `putWord8` (`toEnum` (`ctorIndex` t)) `<>` `gfoldMap` \@`Binary` `put` t -- @ ctorIndex :: forall t. ADT t => t -> Int ctorIndex = I.index $ I.generic @I.AnyType @_ @t @t (I.Ctor (const 0) 1) {-# INLINE ctorIndex #-} ctorIndex1 :: forall t a. ADT1 t => t a -> Int ctorIndex1 = I.index $ I.generic1 @I.AnyType @_ @t @t (const $ I.Ctor (const 0) 1) (I.Ctor (const 0) 1) {-# INLINE ctorIndex1 #-} -- | Any type is instance of `AnyType`, you can use it with @\@`AnyType`@ -- if you don't actually need a class constraint. class AnyType (a :: k) instance AnyType (a :: k)