packages feed

hypertypes-0.2.2: src/Hyper/Type/Pure.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}

-- | A 'Hyper.Type.HyperType' 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).
module Hyper.Type.Pure
    ( Pure (..)
    , _Pure
    , W_Pure (..)
    ) where

import Control.Lens (iso)
import Hyper.TH.Traversable (makeHTraversableApplyAndBases)
import Hyper.Type (type (#), type (:#))
import Text.PrettyPrint.HughesPJClass (Pretty (..))

import Hyper.Internal.Prelude

-- | A 'Hyper.Type.HyperType' to express the simplest plain form of a nested higher-kinded data structure
newtype Pure h = Pure (h :# Pure)
    deriving stock (Generic)

makeHTraversableApplyAndBases ''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 'Hyper.Type.HyperType'.
{-# INLINE _Pure #-}
_Pure :: Iso (Pure # h) (Pure # j) (h # Pure) (j # Pure)
_Pure = iso (\(Pure x) -> x) Pure

instance Pretty (h :# Pure) => Pretty (Pure h) where
    pPrintPrec lvl p (Pure x) = pPrintPrec lvl p x