Skip to content

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)
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information