{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Generic.HKD.Construction
( Construct (..)
) where
import Data.Generic.HKD.Types (HKD (..), GHKD_)
import Data.Kind (Type)
import GHC.Generics
class Construct (f :: Type -> Type) (structure :: Type) where
construct :: HKD structure f -> f structure
deconstruct :: structure -> HKD structure f
class GConstruct (f :: Type -> Type) (rep :: Type -> Type) where
gconstruct :: GHKD_ f rep p -> f (rep p)
gdeconstruct :: rep p -> GHKD_ f rep p
instance (Functor f, GConstruct f inner)
=> GConstruct f (M1 index meta inner) where
gconstruct = fmap M1 . gconstruct . unM1
gdeconstruct = M1 . gdeconstruct @f . unM1
instance (Applicative f, GConstruct f left, GConstruct f right)
=> GConstruct f (left :*: right) where
gconstruct (l :*: r) = (:*:) <$> gconstruct l <*> gconstruct r
gdeconstruct (l :*: r) = gdeconstruct @f l :*: gdeconstruct @f r
instance Applicative f => GConstruct f (K1 index inner) where
gconstruct (K1 x) = fmap K1 x
gdeconstruct (K1 x) = K1 (pure x)
instance (Applicative f, Generic structure, GConstruct f (Rep structure))
=> Construct f structure where
construct = fmap to . gconstruct . runHKD
deconstruct = HKD . gdeconstruct @f . from