{-# LANGUAGE DeriveFunctor
#-}------------------------------------------------------------------------------- |-- Module : Data.Monoid.Deletable-- Copyright : (c) 2011 diagrams-core team (see LICENSE)-- License : BSD-style (see LICENSE)-- Maintainer : diagrams-discuss@googlegroups.com---- A monoid transformer that allows deleting information from a-- concatenation of monoidal values.-------------------------------------------------------------------------------moduleData.Monoid.Deletable(Deletable(..),unDelete,toDeletable,deleteL,deleteR)whereimportData.Semigroup-- | If @m@ is a 'Monoid', then @Deletable m@ (intuitively speaking)-- adds two distinguished new elements @[@ and @]@, such that an-- occurrence of [ \"deletes\" everything from it to the next ]. For-- example,---- > abc[def]gh == abcgh---- This is all you really need to know to /use/ @Deletable m@-- values; to understand the actual implementation, read on.---- To properly deal with nesting and associativity we need to be-- able to assign meanings to things like @[[@, @][@, and so on. (We-- cannot just define, say, @[[ == [@, since then @([[)] == [] ==-- id@ but @[([]) == [id == [@.) Formally, elements of @Deletable-- m@ are triples of the form (r, m, l) representing words @]^r m-- [^l@. When combining two triples (r1, m1, l1) and (r2, m2, l2)-- there are three cases:---- * If l1 == r2 then the [s from the left and ]s from the right-- exactly cancel, and we are left with (r1, m1 \<\> m2, l2).---- * If l1 < r2 then all of the [s cancel with some of the ]s, but-- m1 is still inside the remaining ]s and is deleted, yielding (r1-- + r2 - l1, m2, l2)---- * The remaining case is symmetric with the second.dataDeletablem=DeletableIntmIntderivingFunctor-- | Project the wrapped value out of a `Deletable` value.unDelete::Deletablem->munDelete(Deletable_m_)=m-- | Inject a value into a `Deletable` wrapper. Satisfies the-- property---- > unDelete . toDeletable === id--toDeletable::m->DeletablemtoDeletablem=Deletable0m0instanceSemigroupm=>Semigroup(Deletablem)where(Deletabler1m1l1)<>(Deletabler2m2l2)|l1==r2=Deletabler1(m1<>m2)l2|l1<r2=Deletable(r1+r2-l1)m2l2|otherwise=Deletabler1m1(l2+l1-r2)instance(Semigroupm,Monoidm)=>Monoid(Deletablem)wheremempty=Deletable0mempty0mappend=(<>)-- | A \"left bracket\", which causes everything between it and the-- next right bracket to be deleted.deleteL::Monoidm=>DeletablemdeleteL=Deletable0mempty1-- | A \"right bracket\", denoting the end of the section that should-- be deleted.deleteR::Monoidm=>DeletablemdeleteR=Deletable1mempty0