{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Data.Constraint.Extras
(
Has(..)
, argDict'
, argDictV
, Has'
, has'
, HasV
, hasV
, whichever
, Implies1(..)
) 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 Has c f where
has :: forall a r. f a -> (c a => r) -> r
has f a
x c a => r
r | Dict (c a)
Dict <- f a -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k).
Has c f =>
f a -> Dict (c a)
argDict @c f a
x = r
c a => r
r
argDict :: forall a. f a -> Dict (c a)
argDict f a
x = f a -> (c a => Dict (c a)) -> Dict (c a)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @c f a
x c a => Dict (c a)
forall (a :: Constraint). a => Dict a
Dict
{-# MINIMAL has | argDict #-}
instance (Has c f, Has c g) => Has c (f :+: g) where
argDict :: (:+:) 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).
Has c f =>
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).
Has c f =>
f a -> Dict (c a)
argDict g a
g
instance (Has c f, Has c g) => Has c (Sum f g) where
argDict :: 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).
Has c f =>
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).
Has c f =>
f a -> Dict (c a)
argDict g a
g
type Has' (c :: k -> Constraint) f (g :: k' -> k) = Has (ComposeC c g) f
type HasV c f g = Has (FlipC (ComposeC c) g) f
argDict' :: forall c g f a. (Has' c f g) => f a -> Dict (c (g a))
argDict' :: f a -> Dict (c (g a))
argDict' f a
x = f a -> (ComposeC c g a => Dict (c (g a))) -> Dict (c (g a))
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @(ComposeC c g) f a
x ComposeC c g a => Dict (c (g a))
forall (a :: Constraint). a => Dict a
Dict
argDictV :: forall f c g v. (HasV c f g) => f v -> Dict (c (v g))
argDictV :: f v -> Dict (c (v g))
argDictV f v
x = f v -> (FlipC (ComposeC c) g v => Dict (c (v g))) -> Dict (c (v g))
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @(FlipC (ComposeC c) g) f v
x FlipC (ComposeC c) g v => Dict (c (v g))
forall (a :: Constraint). a => Dict a
Dict
has' :: forall c g f a r. (Has' c f g) => f a -> (c (g a) => r) -> r
has' :: f a -> (c (g a) => r) -> r
has' f a
k c (g a) => r
r = f a -> (ComposeC c g a => r) -> r
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @(ComposeC c g) f a
k c (g a) => r
ComposeC c g a => r
r
hasV :: forall c g f v r. (HasV c f g) => f v -> (c (v g) => r) -> r
hasV :: f v -> (c (v g) => r) -> r
hasV f v
k c (v g) => r
r = f v -> (FlipC (ComposeC c) g v => r) -> r
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @(FlipC (ComposeC c) g) f v
k c (v g) => r
FlipC (ComposeC c) g v => r
r
whichever :: forall c t a r. ForallF c t => (c (t a) => r) -> r
whichever :: (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