{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Data.Constraint.Extras
(
ArgDict(..)
, ConstraintsFor'
, argDict'
, ConstraintsForV
, argDictV
, Has
, has
, Has'
, has'
, HasV
, hasV
, whichever
, Implies1(..)
, ArgDictV
) where
import Data.Constraint
import Data.Constraint.Compose
import Data.Constraint.Flip
import Data.Constraint.Forall
import Data.Functor.Sum (Sum(..))
import Data.Kind
import GHC.Generics ((:+:)(..))
class ArgDict (c :: k -> Constraint) (f :: k -> Type) where
type ConstraintsFor f c :: Constraint
argDict :: ConstraintsFor f c => f a -> Dict (c a)
instance (ArgDict c f, ArgDict c g) => ArgDict c (f :+: g) where
type ConstraintsFor (f :+: g) c = (ConstraintsFor f c, ConstraintsFor g c)
argDict :: forall (a :: k).
ConstraintsFor (f :+: g) c =>
(:+:) f g a -> Dict (c a)
argDict = \case
L1 f a
f -> f a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict f a
f
R1 g a
g -> g a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict g a
g
instance (ArgDict c f, ArgDict c g) => ArgDict c (Sum f g) where
type ConstraintsFor (Sum f g) c = (ConstraintsFor f c, ConstraintsFor g c)
argDict :: forall (a :: k).
ConstraintsFor (Sum f g) c =>
Sum f g a -> Dict (c a)
argDict = \case
InL f a
f -> f a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict f a
f
InR g a
g -> g a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict g a
g
type ConstraintsFor' f (c :: k -> Constraint) (g :: k' -> k) = ConstraintsFor f (ComposeC c g)
argDict' :: forall f c g a. (Has' c f g) => f a -> Dict (c (g a))
argDict' :: forall {k'} {k} (f :: k' -> *) (c :: k -> Constraint)
(g :: k' -> k) (a :: k').
Has' c f g =>
f a -> Dict (c (g a))
argDict' f a
tag = case f a -> Dict (ComposeC c g a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict f a
tag of
(Dict (ComposeC c g a)
Dict :: Dict (ComposeC c g a)) -> Dict (c (g a))
forall (a :: Constraint). a => Dict a
Dict
type ConstraintsForV (f :: (k -> k') -> Type) (c :: k' -> Constraint) (g :: k) = ConstraintsFor f (FlipC (ComposeC c) g)
argDictV :: forall f c g v. (HasV c f g) => f v -> Dict (c (v g))
argDictV :: forall {k} {k'} (f :: (k -> k') -> *) (c :: k' -> Constraint)
(g :: k) (v :: k -> k').
HasV c f g =>
f v -> Dict (c (v g))
argDictV f v
tag = case f v -> Dict (FlipC (ComposeC c) g v)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict f v
tag of
(Dict (FlipC (ComposeC c) g v)
Dict :: Dict (FlipC (ComposeC c) g a)) -> Dict (c (v g))
forall (a :: Constraint). a => Dict a
Dict
{-# DEPRECATED ArgDictV "Just use 'ArgDict'" #-}
type ArgDictV f c = ArgDict f c
type Has (c :: k -> Constraint) f = (ArgDict c f, ConstraintsFor f c)
type Has' (c :: k -> Constraint) f (g :: k' -> k) = (ArgDict (ComposeC c g) f, ConstraintsFor' f c g)
type HasV c f g = (ArgDict (FlipC (ComposeC c) g) f, ConstraintsForV f c g)
has :: forall c f a r. Has c f => f a -> (c a => r) -> r
has :: forall {k} (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has f a
k c a => r
r | (Dict (c a)
Dict :: Dict (c a)) <- f a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
(ArgDict c f, ConstraintsFor f c) =>
f a -> Dict (c a)
argDict f a
k = r
c a => r
r
has' :: forall c g f a r. Has' c f g => f a -> (c (g a) => r) -> r
has' :: forall {k} {k'} (c :: k -> Constraint) (g :: k' -> k)
(f :: k' -> *) (a :: k') r.
Has' c f g =>
f a -> (c (g a) => r) -> r
has' f a
k c (g a) => r
r | (Dict (c (g a))
Dict :: Dict (c (g a))) <- f a -> Dict (c (g a))
forall {k'} {k} (f :: k' -> *) (c :: k -> Constraint)
(g :: k' -> k) (a :: k').
Has' c f g =>
f a -> Dict (c (g a))
argDict' f a
k = r
c (g a) => r
r
hasV :: forall c g f v r. HasV c f g => f v -> (c (v g) => r) -> r
hasV :: forall {k'} {k} (c :: k' -> Constraint) (g :: k)
(f :: (k -> k') -> *) (v :: k -> k') r.
HasV c f g =>
f v -> (c (v g) => r) -> r
hasV f v
k c (v g) => r
r | (Dict (c (v g))
Dict :: Dict (c (v g))) <- f v -> Dict (c (v g))
forall {k} {k'} (f :: (k -> k') -> *) (c :: k' -> Constraint)
(g :: k) (v :: k -> k').
HasV c f g =>
f v -> Dict (c (v g))
argDictV f v
k = r
c (v g) => r
r
whichever :: forall c t a r. ForallF c t => (c (t a) => r) -> r
whichever :: forall {k2} {k1} (c :: k2 -> Constraint) (t :: k1 -> k2) (a :: k1)
r.
ForallF c t =>
(c (t a) => r) -> r
whichever c (t a) => r
r = c (t a) => r
r (c (t a) => r) -> (ForallF c t :- c (t a)) -> r
forall (c :: Constraint) e r. HasDict c e => (c => r) -> e -> r
\\ (ForallF c t :- c (t a)
forall {k2} {k1} (p :: k2 -> Constraint) (f :: k1 -> k2) (a :: k1).
ForallF p f :- p (f a)
instF :: ForallF c t :- c (t a))
class Implies1 c d where
implies1 :: c a :- d a