    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeOperators, GeneralizedNewtypeDeriving, Trustworthy #-}
    module System.Console.Wizard.BasicIO
            ( BasicIO
            , basicIO
            ) where
    import System.Console.Wizard
    import System.Console.Wizard.Internal
    import Control.Monad.Trans
    import Control.Monad.Trans.Maybe

    instance Run IO Output      where runAlgebra (Output s w)        = putStr s   >> w
    instance Run IO OutputLn    where runAlgebra (OutputLn s w)      = putStrLn s >> w
    instance Run IO Line        where runAlgebra (Line s w)          = getLine    >>= w
    instance Run IO Character   where runAlgebra (Character s w)     = getChar    >>= w
    instance Run IO ArbitraryIO where runAlgebra (ArbitraryIO iov f) = iov        >>= f

    -- | The 'BasicIO' backend supports only simple input and output.
    --   Support for 'Password' and 'LinePrewritten' features can be added with
    --   a shim from 'System.Console.Wizard.Shim'.
    newtype BasicIO a = BasicIO (( Output
                               :+: OutputLn
                               :+: Line
                               :+: Character
                               :+: ArbitraryIO) a)
                      deriving ( (:<:) Output
                               , (:<:) OutputLn
                               , (:<:) Line
                               , (:<:) Character
                               , (:<:) ArbitraryIO
                               , Functor
                               , Run IO
                               )

    -- | A simple identity function, used to restrict types if the type inferred by GHC is too general.
    --   You could achieve the same effect with a type signature, but this is slightly less typing.
    basicIO :: Wizard BasicIO a -> Wizard BasicIO a
    basicIO = id