{-# LANGUAGE TypeFamilies #-}
module Data.Lens.Edit.Stateful where

import Data.Lens.Bidirectional
import Data.Monoid

class Bidirectional l => Lens l where
	type C l
	missing :: l -> C l
	dputr   :: l -> (L l, C l) -> (R l, C l)
	dputl   :: l -> (R l, C l) -> (L l, C l)

-- Morally, we have
-- foldMap :: Monoid b => (a -> State c b) -> ([a] -> State c b)
-- which does just what we want.  Unfortunately, this requires an
-- instance (Monad m, Monoid a) => Monoid (m a)
-- and an unhealthy amount of type munging to get in and out of State, curry
-- arguments, etc.  Since the instance above is most conveniently available
-- from the "reducers" package, which has a dependency redwood, and the
-- above-mentioned type-munging obfuscates the beautiful definition anyway, we
-- instead re-implement foldMap manually. It's not quite as beautiful
-- conceptually, but it makes for much easier reading.

foldState :: Monoid dY => (dX -> c -> (dY, c)) -> ([dX], c) -> (dY, c)
foldState f ([]  , c) = (mempty, c)
foldState f (e:es, c) = (mappend e1 e2, c'') where
	(e2, c' ) = foldState f (es, c)
	(e1, c'') = f e c'