> {-# LANGUAGE GADTs #-}
> {-# LANGUAGE KindSignatures #-}
> {-# LANGUAGE PolyKinds #-}
> {-# LANGUAGE ScopedTypeVariables #-}
> {-# LANGUAGE TemplateHaskell #-}
> {-# LANGUAGE TypeApplications #-}
> {-# LANGUAGE TypeFamilies #-}
> {-# LANGUAGE FlexibleContexts #-}
> {-# LANGUAGE ConstraintKinds #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# LANGUAGE UndecidableInstances #-}
> {-# LANGUAGE ExistentialQuantification #-}
> {-# LANGUAGE TypeFamilies #-}
>
> import Data.Aeson
> import Data.Constraint.Forall
> import Data.Constraint.Extras
> import Data.Constraint.Extras.TH
>
> data A :: * -> * where
> A_a :: A Int
> A_b :: Int -> A ()
>
> deriveArgDict ''A
>
> data B :: * -> * where
> B_a :: A a -> A a -> B a
> B_x :: Int -> B Int
>
> deriveArgDict ''B
>
> data V :: (* -> *) -> * where
> V_a :: A Int -> V A
>
> deriveArgDict ''V
>
> data family Fam a :: * -> *
> data instance Fam () :: * -> * where
> FI :: Fam () Int
> FB :: Fam () Bool
>
> deriveArgDict 'FI
> -- this derives an instance Has c (Fam ()) by looking up the associated data instance.
>
> data DSum k f = forall a. DSum (k a) (f a)
>
> -- Derive a ToJSON instance for our 'DSum'
> instance forall k f.
> ( Has' ToJSON k f -- Given a value of type (k a), we can obtain an instance (ToJSON (f a))
> , ForallF ToJSON k -- For any (a), we have an instance (ToJSON (k a))
> ) => ToJSON (DSum k f) where
> toJSON (DSum (k :: k a) f) = toJSON
> ( whichever @ToJSON @k @a $ toJSON k -- Use the (ForallF ToJSON k) constraint to obtain the (ToJSON (k a)) instance
> , has' @ToJSON @f k $ toJSON f -- Use the (Has' ToJSON k f) constraint to obtain the (ToJSON (f a)) instance
> )
>
> data Some k = forall a. Some (k a)
>
> -- Derive a FromJSON instance for our 'DSum'
> instance (FromJSON (Some f), Has' FromJSON f g) => FromJSON (DSum f g) where
> parseJSON x = do
> (jf, jg) <- parseJSON x
> Some (f :: f a) <- parseJSON jf
> g <- has' @FromJSON @g f (parseJSON jg)
> return $ DSum f g
>
> main :: IO ()
> main = return ()

Changes

Revision history for constraints-extras

0.4.0.0 - 2022-11-18

Make Has from a type synonym into the class upon which everything else is based. Instances may define either has or argDict which are now both methods of Has. This should hopefully improve the readability of type errors involving the library a fair bit, as everything wanted to use Has, but it was defined in terms of the less commonly appearing ArgDict and ConstraintsFor.

The ConstraintsFor type family has been removed as it is now unnecessary, as instances of Has can simply be constrained directly. This has the added benefit of allowing QuantifiedConstraints in those instance heads that formerly would not have been allowed as part of the result of a type family.

The ArgDict class has also been removed, as it was also basically never used on its own.

0.3.2.1 - 2021-12-17

Support GHC 9.2

0.3.2.0 - 2021-10-28

Provide ArgDict instances for sums of functors.

0.3.1.0 - 2021-03-24

Allow deriving instances with deriveArgDict for data and newtype family instances by supplying the name of one of its constructors

Support GHC 9.0.1

0.3.0.3 - 2020-06-22

Update version bounds for GHC 8.10

0.3.0.2 - 2019-09-30

Update version bounds for GHC 8.8

0.3.0.1 - 2019-05-17

Drop markdown-unlit in favor of using regular “Bird”-style LHS to avoid some cross-compilation problems

0.3 - 2019-05-16

Added a parameter for the type class, to allow for custom not-fully-polymorphic instances of ArgDict in cases where e.g. your key type contains dictionaries for specific classes. You will now need FlexibleInstances, MultiParamTypeClasses for the instances created by deriveArgDict.

0.2.3.5 - 2019-05-04

Bumped version bounds on base and template-haskell to admit the versions from GHC 8.6.x

0.2.3.4 - 2019-03-22

Added ChangeLog.md

Replaced some occurrences of <> in Data.Constraint.Extras.TH with ++ so that the module will hopefully build with GHC 8.0.2 and 8.2.2 without needing to import Data.Semigroup.