-- | A 'AST.Knot.Knot' to express the simplest plain form of a nested higher-kinded data structure. -- -- The value level [hyperfunctions](http://hackage.haskell.org/package/hyperfunctions) -- equivalent of 'Pure' is called @self@ in -- [Hyperfunctions papers](https://arxiv.org/abs/1309.5135). {-# LANGUAGE UndecidableInstances, TemplateHaskell #-} module AST.Knot.Pure ( Pure(..), _Pure, KWitness(..) , (&#) ) where import AST.Class.Nodes (KNodes(..)) import AST.Knot (Tree, type (#)) import AST.TH.Internal.Instances (makeCommonInstances) import AST.TH.Traversable (makeKTraversableApplyAndBases) import Control.Lens (Iso, iso) import Control.Lens.Operators import GHC.Generics (Generic) import Text.PrettyPrint.HughesPJClass (Pretty(..)) -- | A 'AST.Knot.Knot' to express the simplest plain form of a nested higher-kinded data structure newtype Pure k = Pure (k # Pure) deriving stock Generic makeKTraversableApplyAndBases ''Pure makeCommonInstances [''Pure] -- | An 'Iso' from 'Pure' to its content. -- -- Using `_Pure` rather than the 'Pure' data constructor is recommended, -- because it helps the type inference know that 'Pure' is parameterized with a 'AST.Knot.Knot'. {-# INLINE _Pure #-} _Pure :: Iso (Tree Pure k) (Tree Pure j) (Tree k Pure) (Tree j Pure) _Pure = iso (\(Pure x) -> x) Pure -- | An operator to apply a function to a value and wrap it with 'Pure'. -- -- Helps value construction be more succinct. -- -- The etymology and fixity of '&#' operator mimics '&'. -- -- >>> x &# f -- Pure (f x) infixl 1 &# {-# INLINE (&#) #-} (&#) :: a -> (a -> Tree k Pure) -> Tree Pure k x &# f = _Pure # f x instance Pretty (k # Pure) => Pretty (Pure k) where pPrintPrec lvl p (Pure x) = pPrintPrec lvl p x