{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, 
             TypeOperators, DataKinds, KindSignatures #-}

module Control.Effect.WriteOnceWriter (put, WriteOnce(..)) where

import Control.Effect
import Control.Effect.Helpers.List
import Prelude hiding (Monad(..))

{-| Provides a kind of writer monad, which can only write an item once 
   (no accumulation), an effect system as a list of the items that have been written -}

data WriteOnce (w :: [*]) a = W { runWriteOnce :: (a, List w) }

instance Effect WriteOnce where
    type Inv WriteOnce s t = ()

    {-| Pure effect is the empty list -}
    type Unit WriteOnce = '[]

    {-| Combine effects by appending effect information -}
    type Plus WriteOnce s t = s :++ t

    return x = W (x, Nil)
    (W (a, r)) >>= k = let (W (b, s)) = k a in W (b, r `append` s)

{-| Write a value of type 'a' -}
put :: a -> WriteOnce '[a] ()
put x = W ((), Cons x Nil)