{-# LANGUAGE GADTs #-}
-- |
-- The `build` function can be used to construct multi-line string literals in
-- a monadic way:
--
-- > {-# LANGUAGE OverloadedStrings #-}
-- >
-- > import Data.String.Builder
-- >
-- > mystring :: String
-- > mystring = build $ do
-- >   "foo"
-- >   "bar"
-- >   "baz"
module Data.String.Builder (
-- * Functions
  build
, literal
-- * Types
, Builder
, BuilderM
) where

import Data.String

-- | A writer monad for string literals.
data BuilderM a = BuilderM a ShowS

instance Monad BuilderM where
  return a            = BuilderM a id
  BuilderM a xs >>= f = case f a of
    BuilderM b ys -> BuilderM b (xs . ys)

type Builder = BuilderM ()

-- | Add a literal string.
literal :: String -> Builder
literal = BuilderM () . showString

instance (a ~ ()) => IsString (BuilderM a) where
  fromString s = literal s >> literal "\n"

-- | Run a builder.
build :: Builder -> String
build (BuilderM () s) = s ""