{-# OPTIONS_GHC -Wno-redundant-constraints #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Util.Type
( type (==)
, If
, type (++)
, IsElem
, type (/)
, type (//)
, Guard
, FailWhen
, FailUnless
, failUnlessEvi
, failWhenEvi
, AllUnique
, RequireAllUnique
, ReifyList (..)
, PatternMatch
, PatternMatchL
, KnownList (..)
, KList (..)
, RSplit
, rsplit
, Some1 (..)
, recordToSomeList
, reifyTypeEquality
, ConcatListOfTypesAssociativity
, listOfTypesConcatAssociativityAxiom
, MockableConstraint (..)
, onFirst
) where
import Data.Constraint ((:-)(..), Dict(..), (\\))
import qualified Data.Kind as Kind
import Data.Type.Bool (type (&&), If, Not)
import Data.Type.Equality (type (==))
import Data.Vinyl.Core (Rec(..))
import qualified Data.Vinyl.Functor as Vinyl
import Data.Vinyl.Recursive (recordToList, rmap)
import Data.Vinyl.TypeLevel (type (++))
import GHC.TypeLits (ErrorMessage(..), Symbol, TypeError)
import Unsafe.Coerce (unsafeCoerce)
type family IsElem (a :: k) (l :: [k]) :: Bool where
IsElem _ '[] = 'False
IsElem a (a ': _) = 'True
IsElem a (_ ': as) = IsElem a as
type family (l :: [k]) / (a :: k) where
'[] / _ = '[]
(a ': xs) / a = xs / a
(b ': xs) / a = b ': (xs / a)
type family (l1 :: [k]) // (l2 :: [k]) :: [k] where
l // '[] = l
l // (x ': xs) = (l / x) // xs
type family Guard (cond :: Bool) (a :: k) :: Maybe k where
Guard 'False _ = 'Nothing
Guard 'True a = 'Just a
type family FailUnless (cond :: Bool) (msg :: ErrorMessage) :: Constraint where
FailUnless 'True _ = ()
FailUnless 'False msg = TypeError msg
type FailWhen cond msg = FailUnless (Not cond) msg
failUnlessEvi :: forall cond msg. FailUnless cond msg :- (cond ~ 'True)
failUnlessEvi :: FailUnless cond msg :- (cond ~ 'True)
failUnlessEvi = (FailUnless cond msg => Dict (cond ~ 'True))
-> FailUnless cond msg :- (cond ~ 'True)
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub FailUnless cond msg => Dict (cond ~ 'True)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe
failWhenEvi :: forall cond msg. FailWhen cond msg :- (cond ~ 'False)
failWhenEvi :: FailWhen cond msg :- (cond ~ 'False)
failWhenEvi = (FailWhen cond msg => Dict (cond ~ 'False))
-> FailWhen cond msg :- (cond ~ 'False)
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub FailWhen cond msg => Dict (cond ~ 'False)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe
type family AllUnique (l :: [k]) :: Bool where
AllUnique '[] = 'True
AllUnique (x : xs) = Not (IsElem x xs) && AllUnique xs
type RequireAllUnique desc l = RequireAllUnique' desc l l
type family RequireAllUnique' (desc :: Symbol) (l :: [k]) (origL ::[k]) :: Constraint where
RequireAllUnique' _ '[] _ = ()
RequireAllUnique' desc (x : xs) origL =
If (IsElem x xs)
(TypeError ('Text "Duplicated " ':<>: 'Text desc ':<>: 'Text ":" ':$$:
'ShowType x ':$$:
'Text "Full list: " ':<>:
'ShowType origL
)
)
(RequireAllUnique' desc xs origL)
type family PatternMatch (a :: Kind.Type) :: Constraint where
PatternMatch Int = ((), ())
PatternMatch _ = ()
type family PatternMatchL (l :: [k]) :: Constraint where
PatternMatchL '[] = ((), ())
PatternMatchL _ = ()
class ReifyList (c :: k -> Constraint) (l :: [k]) where
reifyList :: (forall a. c a => Proxy a -> r) -> [r]
instance ReifyList c '[] where
reifyList :: (forall (a :: k). c a => Proxy a -> r) -> [r]
reifyList _ = []
instance (c x, ReifyList c xs) => ReifyList c (x ': xs) where
reifyList :: (forall (a :: a). c a => Proxy a -> r) -> [r]
reifyList reifyElem :: forall (a :: a). c a => Proxy a -> r
reifyElem = Proxy x -> r
forall (a :: a). c a => Proxy a -> r
reifyElem (Proxy x
forall k (t :: k). Proxy t
Proxy @x) r -> [r] -> [r]
forall a. a -> [a] -> [a]
: (forall (a :: a). c a => Proxy a -> r) -> [r]
forall k (c :: k -> Constraint) (l :: [k]) r.
ReifyList c l =>
(forall (a :: k). c a => Proxy a -> r) -> [r]
reifyList @_ @c @xs forall (a :: a). c a => Proxy a -> r
reifyElem
reifyTypeEquality :: forall a b x. (a == b) ~ 'True => (a ~ b => x) -> x
reifyTypeEquality :: ((a ~ b) => x) -> x
reifyTypeEquality x :: (a ~ b) => x
x = (a ~ b) => x
x ((a ~ b) => x) -> Dict (a ~ b) -> x
forall (c :: Constraint) e r. HasDict c e => (c => r) -> e -> r
\\ MockableConstraint (a ~ b) => Dict (a ~ b)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @(a ~ b)
class KnownList l where
klist :: KList l
instance KnownList '[] where
klist :: KList '[]
klist = KList '[]
forall k. KList '[]
KNil
instance KnownList xs => KnownList (x ': xs) where
klist :: KList (x : xs)
klist = Proxy x -> Proxy xs -> KList (x : xs)
forall k (xs :: [k]) (x :: k).
KnownList xs =>
Proxy x -> Proxy xs -> KList (x : xs)
KCons Proxy x
forall k (t :: k). Proxy t
Proxy Proxy xs
forall k (t :: k). Proxy t
Proxy
data KList (l :: [k]) where
KNil :: KList '[]
KCons :: KnownList xs => Proxy x -> Proxy xs -> KList (x ': xs)
type RSplit l r = KnownList l
rsplit
:: forall k (l :: [k]) (r :: [k]) f.
(RSplit l r)
=> Rec f (l ++ r) -> (Rec f l, Rec f r)
rsplit :: Rec f (l ++ r) -> (Rec f l, Rec f r)
rsplit = case KnownList l => KList l
forall k (l :: [k]). KnownList l => KList l
klist @l of
KNil -> (Rec f l
forall u (a :: u -> *). Rec a '[]
RNil, )
KCons{} -> \(x :: f r
x :& r :: Rec f rs
r) ->
let (x1 :: Rec f xs
x1, r1 :: Rec f r
r1) = Rec f (xs ++ r) -> (Rec f xs, Rec f r)
forall k (l :: [k]) (r :: [k]) (f :: k -> *).
RSplit l r =>
Rec f (l ++ r) -> (Rec f l, Rec f r)
rsplit Rec f rs
Rec f (xs ++ r)
r
in (f r
x f r -> Rec f xs -> Rec f (r : xs)
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec f xs
x1, Rec f r
r1)
data Some1 (f :: k -> Kind.Type) =
forall a. Some1 (f a)
deriving stock instance (forall a. Show (f a)) => Show (Some1 f)
recordToSomeList :: Rec f l -> [Some1 f]
recordToSomeList :: Rec f l -> [Some1 f]
recordToSomeList = Rec (Const (Some1 f)) l -> [Some1 f]
forall u a (rs :: [u]). Rec (Const a) rs -> [a]
recordToList (Rec (Const (Some1 f)) l -> [Some1 f])
-> (Rec f l -> Rec (Const (Some1 f)) l) -> Rec f l -> [Some1 f]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (x :: k). f x -> Const (Some1 f) x)
-> Rec f l -> Rec (Const (Some1 f)) l
forall u (f :: u -> *) (g :: u -> *) (rs :: [u]).
(forall (x :: u). f x -> g x) -> Rec f rs -> Rec g rs
rmap (Some1 f -> Const (Some1 f) x
forall k a (b :: k). a -> Const a b
Vinyl.Const (Some1 f -> Const (Some1 f) x)
-> (f x -> Some1 f) -> f x -> Const (Some1 f) x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f x -> Some1 f
forall k (f :: k -> *) (a :: k). f a -> Some1 f
Some1)
type ConcatListOfTypesAssociativity a b c = ((a ++ b) ++ c) ~ (a ++ (b ++ c))
listOfTypesConcatAssociativityAxiom :: forall a b c . Dict (ConcatListOfTypesAssociativity a b c)
listOfTypesConcatAssociativityAxiom :: Dict (ConcatListOfTypesAssociativity a b c)
listOfTypesConcatAssociativityAxiom = Dict (ConcatListOfTypesAssociativity a b c)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe
class MockableConstraint (c :: Constraint) where
provideConstraintUnsafe :: Dict c
instance MockableConstraint (a ~ b) where
provideConstraintUnsafe :: Dict (a ~ b)
provideConstraintUnsafe = Dict (Int ~ Int) -> Dict (a ~ b)
forall a b. a -> b
unsafeCoerce (Dict (Int ~ Int) -> Dict (a ~ b))
-> Dict (Int ~ Int) -> Dict (a ~ b)
forall a b. (a -> b) -> a -> b
$ (Int ~ Int) => Dict (Int ~ Int)
forall (a :: Constraint). a => Dict a
Dict @(Int ~ Int)
instance {-# OVERLAPPABLE #-} c a => MockableConstraint (c a) where
provideConstraintUnsafe :: Dict (c a)
provideConstraintUnsafe = Dict (c a)
forall (a :: Constraint). a => Dict a
Dict
instance ( MockableConstraint c1
, MockableConstraint c2
) => MockableConstraint (c1, c2) where
provideConstraintUnsafe :: Dict (c1, c2)
provideConstraintUnsafe = Identity (Dict (c1, c2)) -> Dict (c1, c2)
forall a. Identity a -> a
runIdentity (Identity (Dict (c1, c2)) -> Dict (c1, c2))
-> Identity (Dict (c1, c2)) -> Dict (c1, c2)
forall a b. (a -> b) -> a -> b
$ do
Dict c1
Dict <- Dict c1 -> Identity (Dict c1)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict c1 -> Identity (Dict c1)) -> Dict c1 -> Identity (Dict c1)
forall a b. (a -> b) -> a -> b
$ MockableConstraint c1 => Dict c1
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @c1
Dict c2
Dict <- Dict c2 -> Identity (Dict c2)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict c2 -> Identity (Dict c2)) -> Dict c2 -> Identity (Dict c2)
forall a b. (a -> b) -> a -> b
$ MockableConstraint c2 => Dict c2
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @c2
Dict (c1, c2) -> Identity (Dict (c1, c2))
forall (m :: * -> *) a. Monad m => a -> m a
return Dict (c1, c2)
forall (a :: Constraint). a => Dict a
Dict
{-# INLINE provideConstraintUnsafe #-}
instance ( MockableConstraint c1
, MockableConstraint c2
, MockableConstraint c3
) => MockableConstraint (c1, c2, c3) where
provideConstraintUnsafe :: Dict (c1, c2, c3)
provideConstraintUnsafe = Identity (Dict (c1, c2, c3)) -> Dict (c1, c2, c3)
forall a. Identity a -> a
runIdentity (Identity (Dict (c1, c2, c3)) -> Dict (c1, c2, c3))
-> Identity (Dict (c1, c2, c3)) -> Dict (c1, c2, c3)
forall a b. (a -> b) -> a -> b
$ do
Dict (c1, c2)
Dict <- Dict (c1, c2) -> Identity (Dict (c1, c2))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict (c1, c2) -> Identity (Dict (c1, c2)))
-> Dict (c1, c2) -> Identity (Dict (c1, c2))
forall a b. (a -> b) -> a -> b
$ MockableConstraint (c1, c2) => Dict (c1, c2)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @(c1, c2)
Dict c3
Dict <- Dict c3 -> Identity (Dict c3)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict c3 -> Identity (Dict c3)) -> Dict c3 -> Identity (Dict c3)
forall a b. (a -> b) -> a -> b
$ MockableConstraint c3 => Dict c3
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @c3
Dict (c1, c2, c3) -> Identity (Dict (c1, c2, c3))
forall (m :: * -> *) a. Monad m => a -> m a
return Dict (c1, c2, c3)
forall (a :: Constraint). a => Dict a
Dict
{-# INLINE provideConstraintUnsafe #-}
instance ( MockableConstraint c1
, MockableConstraint c2
, MockableConstraint c3
, MockableConstraint c4
) => MockableConstraint (c1, c2, c3, c4) where
provideConstraintUnsafe :: Dict (c1, c2, c3, c4)
provideConstraintUnsafe = Identity (Dict (c1, c2, c3, c4)) -> Dict (c1, c2, c3, c4)
forall a. Identity a -> a
runIdentity (Identity (Dict (c1, c2, c3, c4)) -> Dict (c1, c2, c3, c4))
-> Identity (Dict (c1, c2, c3, c4)) -> Dict (c1, c2, c3, c4)
forall a b. (a -> b) -> a -> b
$ do
Dict (c1, c2, c3)
Dict <- Dict (c1, c2, c3) -> Identity (Dict (c1, c2, c3))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict (c1, c2, c3) -> Identity (Dict (c1, c2, c3)))
-> Dict (c1, c2, c3) -> Identity (Dict (c1, c2, c3))
forall a b. (a -> b) -> a -> b
$ MockableConstraint (c1, c2, c3) => Dict (c1, c2, c3)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @(c1, c2, c3)
Dict c4
Dict <- Dict c4 -> Identity (Dict c4)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict c4 -> Identity (Dict c4)) -> Dict c4 -> Identity (Dict c4)
forall a b. (a -> b) -> a -> b
$ MockableConstraint c4 => Dict c4
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @c4
Dict (c1, c2, c3, c4) -> Identity (Dict (c1, c2, c3, c4))
forall (m :: * -> *) a. Monad m => a -> m a
return Dict (c1, c2, c3, c4)
forall (a :: Constraint). a => Dict a
Dict
{-# INLINE provideConstraintUnsafe #-}
instance ( MockableConstraint c1
, MockableConstraint c2
, MockableConstraint c3
, MockableConstraint c4
, MockableConstraint c5
) => MockableConstraint (c1, c2, c3, c4, c5) where
provideConstraintUnsafe :: Dict (c1, c2, c3, c4, c5)
provideConstraintUnsafe = Identity (Dict (c1, c2, c3, c4, c5)) -> Dict (c1, c2, c3, c4, c5)
forall a. Identity a -> a
runIdentity (Identity (Dict (c1, c2, c3, c4, c5)) -> Dict (c1, c2, c3, c4, c5))
-> Identity (Dict (c1, c2, c3, c4, c5))
-> Dict (c1, c2, c3, c4, c5)
forall a b. (a -> b) -> a -> b
$ do
Dict (c1, c2, c3, c4)
Dict <- Dict (c1, c2, c3, c4) -> Identity (Dict (c1, c2, c3, c4))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict (c1, c2, c3, c4) -> Identity (Dict (c1, c2, c3, c4)))
-> Dict (c1, c2, c3, c4) -> Identity (Dict (c1, c2, c3, c4))
forall a b. (a -> b) -> a -> b
$ MockableConstraint (c1, c2, c3, c4) => Dict (c1, c2, c3, c4)
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @(c1, c2, c3, c4)
Dict c5
Dict <- Dict c5 -> Identity (Dict c5)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dict c5 -> Identity (Dict c5)) -> Dict c5 -> Identity (Dict c5)
forall a b. (a -> b) -> a -> b
$ MockableConstraint c5 => Dict c5
forall (c :: Constraint). MockableConstraint c => Dict c
provideConstraintUnsafe @c5
Dict (c1, c2, c3, c4, c5) -> Identity (Dict (c1, c2, c3, c4, c5))
forall (m :: * -> *) a. Monad m => a -> m a
return Dict (c1, c2, c3, c4, c5)
forall (a :: Constraint). a => Dict a
Dict
{-# INLINE provideConstraintUnsafe #-}
onFirst :: Bifunctor p => p a c -> (a -> b) -> p b c
onFirst :: p a c -> (a -> b) -> p b c
onFirst = ((a -> b) -> p a c -> p b c) -> p a c -> (a -> b) -> p b c
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> b) -> p a c -> p b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first