module Data.Coat where

import Prelude
import Control.Lens
import Control.Monad
import Data.Layer


-- Non-monadic interface

class Coated c where
    coated :: Lens (c a) (c a') a a'
    default coated :: (Unwrapped (c a) ~ a, Unwrapped (c a') ~ a', Rewrapping (c a) (c a')) => Lens (c a) (c a') a a'
    coated = _Wrapped


class IsCoat c where
    coat :: a -> c a
    default coat :: (IsLayer (c a), Unlayered (c a) ~ a) => a -> c a
    coat = layer

uncoat :: Coated c => c a -> a
uncoat = view coated


-- Monadic interface

class CoatedM m c where
    viewCoatedM :: c a -> m a
    setCoatedM  :: a -> c a -> m (c a)


uncoatM :: CoatedM m c => c a -> m a
uncoatM = viewCoatedM

withCoatedM :: (CoatedM m c, Monad m) => (a -> m a) -> c a -> m (c a)
withCoatedM f l = viewCoatedM l >>= f >>= flip setCoatedM l

withCoatedM' :: (CoatedM m c, Monad m) => (a -> a) -> c a -> m (c a)
withCoatedM' = withCoatedM . (return .)


class CoatConstructor a m c where constructCoat :: a -> m (c a)
class CoatGenerator     m c where generateCoat  :: a -> m (c a)