{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} {-# language ConstraintKinds #-} {-# language DataKinds #-} {-# language FlexibleContexts #-} {-# language FlexibleInstances #-} {-# language FunctionalDependencies #-} {-# language MultiParamTypeClasses #-} {-# language ScopedTypeVariables #-} {-# language TypeFamilies #-} {-# language TypeOperators #-} {-# language UndecidableInstances #-} module Data.Generics.Internal.Wrapped ( Context , derived ) where import Data.Generics.Internal.Profunctor.Iso import Data.Generics.Internal.Families.Changing ( UnifyHead ) import Data.Kind (Constraint) import GHC.Generics import GHC.TypeLits type Context s t a b = ( Generic s , Generic t , GWrapped (Rep s) (Rep t) a b , UnifyHead s t , UnifyHead t s , ErrorUnlessOnlyOne s (Rep s) ) derived :: Context s t a b => Iso s t a b derived = repIso . gWrapped {-# INLINE derived #-} type family ErrorUnlessOnlyOne a b :: Constraint where ErrorUnlessOnlyOne t (M1 i k a) = ErrorUnlessOnlyOne t a ErrorUnlessOnlyOne t (K1 i a) = () ErrorUnlessOnlyOne t a = TypeError ('ShowType t ':<>: 'Text " is not a single-constructor, single-field datatype") -------------------------------------------------------------------------------- class GWrapped s t a b | s -> a, t -> b, s b -> t, t a -> s where gWrapped :: Iso (s x) (t x) a b instance GWrapped s t a b => GWrapped (M1 i k s) (M1 i k t) a b where gWrapped = mIso . gWrapped instance (a ~ c, b ~ d) => GWrapped (K1 i a) (K1 i b) c d where gWrapped = kIso