hypertypes-0.1.0.1: src/Hyper/Class/Recursive.hs
-- | Classes applying on 'HyperType's recursively
{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
module Hyper.Class.Recursive
( Recursive(..)
, Recursively(..)
, RNodes(..), RTraversable(..)
, proxyArgument
) where
import Hyper.Class.Foldable
import Hyper.Class.Functor (HFunctor(..))
import Hyper.Class.Nodes (HNodes(..))
import Hyper.Class.Traversable
import Hyper.Type
import Hyper.Type.Pure (Pure(..))
import Hyper.Internal.Prelude
-- | A class of constraint constructors that apply to all recursive child nodes
class Recursive c where
-- | Lift a recursive constraint to the next layer
recurse :: (HNodes h, c h) => proxy (c h) -> Dict (HNodesConstraint h c)
-- | A class of 'HyperType's which recursively implement 'HNodes'
class HNodes h => RNodes h where
recursiveHNodes :: proxy h -> Dict (HNodesConstraint h RNodes)
{-# INLINE recursiveHNodes #-}
default recursiveHNodes ::
HNodesConstraint h RNodes =>
proxy h -> Dict (HNodesConstraint h RNodes)
recursiveHNodes _ = Dict
instance RNodes Pure
instance RNodes (Const a)
-- | Helper Proxy combinator that is useful in many instances of 'Recursive'
proxyArgument :: proxy (f h :: Constraint) -> Proxy (h :: HyperType)
proxyArgument _ = Proxy
instance Recursive RNodes where
{-# INLINE recurse #-}
recurse = recursiveHNodes . proxyArgument
-- | A constraint lifted to apply recursively.
--
-- Note that in cases where a constraint has dependencies other than 'RNodes',
-- one will want to create a class such as RTraversable to capture the dependencies,
-- otherwise using it in class contexts will be quite unergonomic.
class RNodes h => Recursively c h where
recursively ::
proxy (c h) -> Dict (c h, HNodesConstraint h (Recursively c))
{-# INLINE recursively #-}
default recursively ::
(c h, HNodesConstraint h (Recursively c)) =>
proxy (c h) -> Dict (c h, HNodesConstraint h (Recursively c))
recursively _ = Dict
instance Recursive (Recursively c) where
{-# INLINE recurse #-}
recurse p =
withDict (recursively (p0 p)) Dict
where
p0 :: proxy (Recursively c h) -> Proxy (c h)
p0 _ = Proxy
instance c Pure => Recursively c Pure
instance c (Const a) => Recursively c (Const a)
-- | A class of 'HyperType's which recursively implement 'HTraversable'
class (HTraversable h, Recursively HFunctor h, Recursively HFoldable h) => RTraversable h where
recursiveHTraversable :: proxy h -> Dict (HNodesConstraint h RTraversable)
{-# INLINE recursiveHTraversable #-}
default recursiveHTraversable ::
HNodesConstraint h RTraversable =>
proxy h -> Dict (HNodesConstraint h RTraversable)
recursiveHTraversable _ = Dict
instance RTraversable Pure
instance RTraversable (Const a)
instance Recursive RTraversable where
{-# INLINE recurse #-}
recurse = recursiveHTraversable . proxyArgument