hypertypes-0.2.2: src/Hyper/Combinator/Flip.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
-- | A combinator to flip the order of the last two type parameters of a 'Hyper.Type.HyperType'.
module Hyper.Combinator.Flip
( HFlip (..)
, _HFlip
, hflipped
, htraverseFlipped
) where
import Control.Lens (from, iso)
import Hyper.Class.Nodes (HWitness)
import Hyper.Class.Traversable (HTraversable, htraverse)
import Hyper.Type (GetHyperType, type (#))
import Hyper.Internal.Prelude
-- | Flip the order of the last two type parameters of a 'Hyper.Type.HyperType'.
--
-- Useful to use instances of classes such as 'Hyper.Class.Traversable.HTraversable' which
-- are available on the flipped 'Hyper.Type.HyperType'.
-- For example 'Hyper.Unify.Generalize.GTerm' has instances when flipped.
newtype HFlip f x h
= MkHFlip (f (GetHyperType h) # x)
deriving stock (Generic)
makeCommonInstances [''HFlip]
-- | An 'Iso' from 'Flip' to its content.
--
-- Using `_Flip` rather than the 'MkFlip' data constructor is recommended,
-- because it helps the type inference know that @ANode c@ is parameterized with a 'Hyper.Type.HyperType'.
_HFlip ::
Iso
(HFlip f0 x0 # k0)
(HFlip f1 x1 # k1)
(f0 k0 # x0)
(f1 k1 # x1)
_HFlip = iso (\(MkHFlip x) -> x) MkHFlip
hflipped ::
Iso
(f0 k0 # x0)
(f1 k1 # x1)
(HFlip f0 x0 # k0)
(HFlip f1 x1 # k1)
hflipped = from _HFlip
-- | Convinience function for traversal over second last 'HyperType' argument.
htraverseFlipped ::
(Applicative f, HTraversable (HFlip h a)) =>
(forall n. HWitness (HFlip h a) n -> p # n -> f (q # n)) ->
h p # a ->
f (h q # a)
htraverseFlipped f = hflipped (htraverse f)