Add Contravariant newtype corresponding to Show
Motivation
We have Contravariant
types corresponding to Eq
and Ord
already, as well as a Functor
type for Read
, so we should have a Contravariant
type corresponding to Show
as well.
Proposal
It's a simple type:
newtype Showing a = Showing { runShowing :: Int -> a -> ShowS }
instance Contravariant Showing where
contramap f (Showing sh) = Showing $ \p -> sh p . f
{-# INLINE contramap #-}
a >$ Showing sh = Showing $ \p _ -> sh p a
{-# INLINE (>$) #-}
The instances for Divisible
and Decidable
in the contravariant
package (if and when that's brought over) should be simple as well:
instance Divisible Showing where
divide f (Showing shb) (Showing shc) = Showing $ \p a -> case f a of
(b, c) -> shb p b . shc p c
{-# INLINE divide #-}
conquer = Showing $ \_ _ -> id
{-# INLINE conquer #-}
instance Decidable Showing where
lose f = Showing $ \_ -> absurd . f
{-# INLINE lose #-}
choose f (Showing shb) (Showing shc) = Showing $ \p -> either (shb p) (shc p) . f
{-# INLINE choose #-}
This also allows the creation of combinators for Showing
to ease the implementation of Show
instances:
showingString :: String -> Showing a
showingString s = Showing $ \_ _ -> showString s
(*<) :: Divisible f => f () -> f a -> f a
(*<) = divide ((,) ())
(>*) :: Divisible f => f a -> f () -> f a
(>*) = divide (\a -> (a, ()))
showingParen :: Int -> Showing a -> Showing a
showingParen pb (Showing sh) = Showing $ \p a -> showParen (p > pb) $ sh (pb + 1) a
showingList :: Showing a -> Showing [a]
showingList (Showing sh) = Showing $ \_ -> showListWith (sh 0)