{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Data.Morpheus.Generic.Fields
( DecoderFun (..),
DecodeFields,
decodeFields,
CountFields (..),
)
where
import Data.Morpheus.Generic.Proxy
( selNameP,
)
import Data.Morpheus.Types.Internal.AST (FieldName)
import GHC.Generics
import Relude
class CountFields (f :: Type -> Type) where
countFields :: Proxy f -> Int
instance (CountFields f, CountFields g) => CountFields (f :*: g) where
countFields _ = countFields (Proxy @f) + countFields (Proxy @g)
instance (Selector s) => CountFields (M1 S s (K1 i a)) where
countFields _ = 1
instance CountFields U1 where
countFields _ = 0
newtype DecoderFun con m = DecoderFun {decoderFun :: forall a. (con a) => FieldName -> m a}
decodeFields :: (Monad m, DecodeFields con f) => DecoderFun con m -> m (f a)
decodeFields ctx = decodeFieldsWith ctx 0
class DecodeFields con (f :: Type -> Type) where
decodeFieldsWith :: (Monad m) => DecoderFun con m -> Int -> m (f a)
instance (DecodeFields val f, DecodeFields val g, CountFields g) => DecodeFields val (f :*: g) where
decodeFieldsWith ctx index =
(:*:)
<$> decodeFieldsWith ctx index
<*> decodeFieldsWith ctx (index + countFields (Proxy @g))
instance (Selector s, con a) => DecodeFields con (M1 S s (K1 i a)) where
decodeFieldsWith ctx index = M1 . K1 <$> decoderFun ctx (getFieldName (selNameP (Proxy @s)) index)
instance DecodeFields val U1 where
decodeFieldsWith _ _ = pure U1
getFieldName :: FieldName -> Int -> FieldName
getFieldName "" index = "_" <> show index
getFieldName label _ = label