Skip to content

Instantly share code, notes, and snippets.

@Lysxia
Created April 2, 2018 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lysxia/67f8eca8b21d3cdb873b08ded24fdbfe to your computer and use it in GitHub Desktop.
Save Lysxia/67f8eca8b21d3cdb873b08ded24fdbfe to your computer and use it in GitHub Desktop.
HKD deriving ToJSON with generic constraints
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Coerce
import Data.Functor.Identity
import Data.Kind
import GHC.Generics
import Data.Aeson
type family HKD s a where
HKD Identity a = a
HKD Maybe a = Maybe a
data Person f = Person
{ pName :: HKD f String
, pAge :: HKD f Int
} deriving (Generic)
type GToJSONFields a = GFields' ToJSON (Rep a)
-- Every field satisfies constraint c
type family GFields' (c :: * -> Constraint) (f :: * -> *) :: Constraint
type instance GFields' c (M1 i d f) = GFields' c f
type instance GFields' c (f :+: g) = (GFields' c f, GFields' c g)
type instance GFields' c (f :*: g) = (GFields' c f, GFields' c g)
type instance GFields' c U1 = ()
type instance GFields' c (K1 i a) = c a
instance (GToJSONFields (Person f)) => ToJSON (Person f)
main = do
print (encode (Person "John" 33 :: Person Identity))
print (encode (Person (Just "John") Nothing :: Person Maybe))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment