kind-generics-deriving-0.3.0.0: src/Generics/Kind/Derive/Traversable.hs
{-# language AllowAmbiguousTypes #-}
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language MultiParamTypeClasses #-}
{-# language PolyKinds #-}
{-# language QuantifiedConstraints #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
{-# language TypeOperators #-}
{-# language UndecidableInstances #-}
module Generics.Kind.Derive.Traversable where
import Data.Kind
import GHC.TypeLits
import Generics.Kind
traverseDefaultPos :: forall v f as bs g.
(GenericK f, GenericK f,
GTraversable (RepK f) v as bs,
Applicative g)
=> (Interpret ('Var v) as -> g (Interpret ('Var v) bs))
-> f :@@: as -> g (f :@@: bs)
traverseDefaultPos f = fmap (toK @_ @f @bs) . gtraverse @_ @(RepK f) @v @as @bs f . fromK @_ @f @as
traverseDefault :: forall f a b g. (GenericK f, GenericK f,
GTraversable (RepK f) 'VZ (LoT1 a) (LoT1 b), Applicative g)
=> (a -> g b) -> f a -> g (f b)
traverseDefault = traverseDefaultPos @'VZ @f @(LoT1 a) @(LoT1 b)
class GTraversable (f :: LoT k -> Type) (v :: TyVar k Type)
(as :: LoT k) (bs :: LoT k) where
gtraverse :: Applicative g
=> (Interpret ('Var v) as -> g (Interpret ('Var v) bs))
-> f as -> g (f bs)
instance GTraversable U1 v as bs where
gtraverse _ U1 = pure U1
instance forall f v as bs i c. GTraversable f v as bs
=> GTraversable (M1 i c f) v as bs where
gtraverse v (M1 x) = M1 <$> gtraverse @_ @f @v @as @bs v x
instance forall f g v as bs. (GTraversable f v as bs, GTraversable g v as bs)
=> GTraversable (f :+: g) v as bs where
gtraverse v (L1 x) = L1 <$> gtraverse @_ @f @v @as @bs v x
gtraverse v (R1 x) = R1 <$> gtraverse @_ @g @v @as @bs v x
instance forall f g v as bs. (GTraversable f v as bs, GTraversable g v as bs)
=> GTraversable (f :*: g) v as bs where
gtraverse v (x :*: y) = (:*:) <$> gtraverse @_ @f @v @as @bs v x
<*> gtraverse @_ @g @v @as @bs v y
instance forall c f v as bs z.
(Interpret c as => GTraversable f v as bs, z ~ Interpret c bs, Interpret c as => z)
=> GTraversable (c :=>: f) v as bs where
gtraverse v (SuchThat x) = SuchThat <$> gtraverse @_ @f @v @as @bs v x
instance forall k f v as bs.
(forall (t :: k). GTraversable f ('VS v) (t ':&&: as) (t ':&&: bs))
=> GTraversable (Exists k f) v as bs where
gtraverse v (Exists (x :: f (t ':&&: x)))
= Exists <$> gtraverse @_ @f @('VS v) @(t ':&&: x) @(t ':&&: _) v x
instance forall t v as bs. GTraversableArg t v as bs (ContainsTyVar v t)
=> GTraversable (Field t) v as bs where
gtraverse v (Field x) = Field <$> gtraversef @_ @t @v @as @bs @(ContainsTyVar v t) v x
class GTraversableArg (t :: Atom d Type) (v :: TyVar d Type)
(as :: LoT d) (bs :: LoT d) (p :: Bool) where
gtraversef :: Applicative g
=> (Interpret ('Var v) as -> g (Interpret ('Var v) bs))
-> Interpret t as -> g (Interpret t bs)
instance (Interpret t as ~ Interpret t bs) => GTraversableArg t v as bs 'False where
gtraversef _ = pure
instance TypeError ('Text "Should never get here")
=> GTraversableArg ('Kon t) v as bs whatever where
gtraversef _ = pure
instance ( Traversable (Interpret f as), Interpret f as ~ Interpret f bs
, GTraversableArg x v as bs (ContainsTyVar v x))
=> GTraversableArg (f ':@: x) v as bs 'True where
gtraversef f x = traverse (gtraversef @_ @x @v @as @bs @(ContainsTyVar v x) f) x
-- We found the same variable
instance GTraversableArg ('Var 'VZ) 'VZ (a ':&&: as) (b ':&&: bs) 'True where
gtraversef f x = f x
-- We need to keep looking
instance forall d (v :: TyVar d Type) n r as s bs isthere.
GTraversableArg ('Var v) n as bs isthere
=> GTraversableArg ('Var ('VS v)) ('VS n) (r ':&&: as) (s ':&&: bs) isthere where
gtraversef f x = gtraversef @d @('Var v) @n @as @bs @isthere f x
-- If we arrive to another we do not want, keep it as it is
instance TypeError ('Text "Should never get here")
=> GTraversableArg ('Var 'VZ) ('VS n) (r ':&&: as) (r ':&&: bs) 'True where
gtraversef _ = pure