Created
April 3, 2018 00:00
-
-
Save Lysxia/791164a92b279222acc212f39f5e8d26 to your computer and use it in GitHub Desktop.
HKD deriving ToJSON by encoding quantified constraints
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE AllowAmbiguousTypes #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE StandaloneDeriving #-} | |
{-# LANGUAGE TypeApplications #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeOperators #-} | |
import Data.Coerce | |
import Data.Functor.Identity | |
import GHC.Generics | |
import Data.Aeson | |
-- "Higher Kinded Data" | |
-- "Defunctionalized application" | |
type family s @@ a | |
type instance Id @@ a = a | |
type instance Tc f @@ a = f a | |
-- Defunctionalization symbols | |
data Id -- Identity function | |
data Tc (f :: * -> *) -- Type constructor | |
data Person f = Person | |
{ pName :: f @@ String | |
, pAge :: f @@ Int | |
} deriving (Generic) | |
gcoerce :: forall a b. (Generic a, Generic b, Coercible (Rep a ()) (Rep b ())) => a -> b | |
gcoerce = to . (coerce :: Rep a () -> Rep b ()) . from | |
instance ToJSON_Apply f => ToJSON (Person f) where | |
toJSON = genericToJSON defaultOptions . gcoerce @_ @(Person (Tc (Apply f))) | |
newtype Apply f a = Apply (f @@ a) | |
instance (ToJSON_Apply f, ToJSON a) => ToJSON (Apply f a) where | |
toJSON (Apply x) = toJSON_Apply @f @a x | |
class ToJSON_Apply f where | |
toJSON_Apply :: ToJSON a => f @@ a -> Value | |
instance ToJSON1 f => ToJSON_Apply (Tc f) where | |
toJSON_Apply = toJSON1 | |
instance ToJSON_Apply Id where | |
toJSON_Apply = toJSON | |
main = do | |
print (encode (Person "John" 33 :: Person Id)) | |
print (encode (Person Nothing (Just 33) :: Person (Tc Maybe))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment