{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
module WriterIO (
    WriterIOT(..)
  , HasHandle(..)
) where

import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer.Strict
import System.IO

newtype WriterIOT m a = WriterIOT { getWriterT :: WriterT () m a }
    deriving (Functor, Applicative, Monad, MonadIO, MonadTrans, MonadReader r, MonadState s)

class HasHandle m where
    getHandle :: m Handle

instance (MonadIO m, HasHandle (WriterIOT m)) => MonadWriter String (WriterIOT m) where
    tell w = do
        h <- getHandle
        liftIO $ hPutStrLn h w
    listen = fmap (\a -> (a,error "cannot read from already written stuff"))
    pass = fmap fst
