{-# LANGUAGE FlexibleInstances #-}

-- |
-- Module      : AutoProof.Internal.Utils.PrettyPrintable
-- Copyright   : (c) Artem Mavrin, 2021
-- License     : BSD3
-- Maintainer  : artemvmavrin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
-- Defines the 'PrettyPrintable' class.
module AutoProof.Internal.Utils.PrettyPrintable
  ( PrettyPrintable (pretty, prettys),
    prettySeq,
    prettysSeq,
  )
where

import qualified AutoProof.Internal.Utils.DList as DList (fromList, toList)
import Data.Foldable (toList)

-- | Class for types that can be "pretty-printed" in a human-readable format.
class PrettyPrintable a where
  {-# MINIMAL pretty | prettys #-}

  -- | Pretty-print a value.
  pretty :: a -> String
  pretty = DList Char -> String
forall a. DList a -> [a]
DList.toList (DList Char -> String) -> (a -> DList Char) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> DList Char
forall a. PrettyPrintable a => a -> DList Char
prettys

  -- | Difference-list representation of a pretty-printed value.
  prettys :: a -> ShowS
  prettys = String -> DList Char
forall a. [a] -> DList a
DList.fromList (String -> DList Char) -> (a -> String) -> a -> DList Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. PrettyPrintable a => a -> String
pretty

instance PrettyPrintable String where
  prettys :: String -> DList Char
prettys = String -> DList Char
showString

-- | Difference-list representation of a pretty-printed collection of
-- pretty-printable values.
prettysSeq :: (Foldable t, PrettyPrintable a) => t a -> ShowS
prettysSeq :: t a -> DList Char
prettysSeq c :: t a
c s :: String
s = case t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList t a
c of
  [] -> String
s
  (p :: a
p : ps :: [a]
ps) -> a -> DList Char
forall a. PrettyPrintable a => a -> DList Char
prettys a
p ([a] -> String
forall a. PrettyPrintable a => [a] -> String
f [a]
ps)
  where
    f :: [a] -> String
f [] = String
s
    f (q :: a
q : qs :: [a]
qs) = ',' Char -> DList Char
forall a. a -> [a] -> [a]
: ' ' Char -> DList Char
forall a. a -> [a] -> [a]
: a -> DList Char
forall a. PrettyPrintable a => a -> DList Char
prettys a
q ([a] -> String
f [a]
qs)

-- | Pretty-print a collection of pretty-printable values.
prettySeq :: (Foldable t, PrettyPrintable a) => t a -> String
prettySeq :: t a -> String
prettySeq c :: t a
c = t a -> DList Char
forall (t :: * -> *) a.
(Foldable t, PrettyPrintable a) =>
t a -> DList Char
prettysSeq t a
c ""