{-
Copyright 2011 Mario Blazevic
This file is part of the Streaming Component Combinators (SCC) project.
The SCC project is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
version.
SCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with SCC. If not, see
<http://www.gnu.org/licenses/>.
-}-- | This module defines the 'Monoid' => 'CancellativeMonoid' => 'GCDMonoid' class hierarchy.-- moduleData.Monoid.Cancellative(-- * ClassesCancellativeMonoid,GCDMonoid,LeftCancellativeMonoid(..),RightCancellativeMonoid(..),LeftGCDMonoid(..),RightGCDMonoid(..))whereimportData.Monoid(Monoid(mappend))importqualifiedData.ListasListimportqualifiedData.ByteStringasByteStringimportqualifiedData.TextasTextimportData.ByteString(ByteString)importData.Text(Text)-- | Class of monoids with a left inverse of 'mappend', satisfying the following law:-- -- > mstripPrefix a (a `mappend` b) == Just b-- > maybe b (a `mappend`) (mstripPrefix a b) == bclassMonoidm=>LeftCancellativeMonoidmwheremstripPrefix::m->m->Maybem-- | Class of monoids with a right inverse of 'mappend', satisfying the following law:-- -- > mstripSuffix b (a `mappend` b) == Just a-- > maybe b (`mappend` a) (mstripSuffix a b) == bclassMonoidm=>RightCancellativeMonoidmwheremstripSuffix::m->m->MaybemclassLeftCancellativeMonoidm=>LeftGCDMonoidmwherecommonPrefix::m->m->mclassRightCancellativeMonoidm=>RightGCDMonoidmwherecommonSuffix::m->m->m-- | Class of monoids for which the 'mappend' operation can be reverted while satisfying the following laws:-- -- > mstripPrefix a (a `mappend` b) == Just b-- > mstripSuffix b (a `mappend` b) == Just a-- > maybe b (a `mappend`) (mstripPrefix a b) == b-- > maybe b (`mappend` a) (mstripSuffix a b) == bclass(LeftCancellativeMonoidm,RightCancellativeMonoidm)=>CancellativeMonoidm-- | Class of monoids that allow the greatest common denominator to be found for any two given values. The operations-- must satisfy the following laws:-- -- > commonPrefix (a `mappend` b) (a `mappend` c) == a `mappend` commonPrefix b c-- > commonSuffix (a `mappend` c) (b `mappend` c) == commonSuffix a b `mappend` cclass(CancellativeMonoidm,LeftGCDMonoidm,RightGCDMonoidm)=>GCDMonoidm-- List instancesinstanceEqx=>LeftCancellativeMonoid[x]wheremstripPrefix=List.stripPrefixinstanceEqx=>LeftGCDMonoid[x]wherecommonPrefix(x:xs)(y:ys)|x==y=x:commonPrefixxsyscommonPrefix__=[]instanceEqx=>RightCancellativeMonoid[x]wheremstripSuffixsl=fmapList.reverse(mstripPrefix(List.reverses)(List.reversel))instanceEqx=>RightGCDMonoid[x]wherecommonSuffixxsys=List.reverse(commonPrefix(List.reversexs)(List.reverseys))instanceEqx=>CancellativeMonoid[x]instanceEqx=>GCDMonoid[x]-- ByteString instancesinstanceLeftCancellativeMonoidByteStringwheremstripPrefixpl=ifByteString.isPrefixOfplthenJust(ByteString.drop(ByteString.lengthp)l)elseNothinginstanceRightCancellativeMonoidByteStringwheremstripSuffixsl=ifByteString.isSuffixOfslthenJust(ByteString.take(ByteString.lengthl-ByteString.lengths)l)elseNothinginstanceCancellativeMonoidByteStringinstanceLeftGCDMonoidByteStringwherecommonPrefixxy=ByteString.takemaxPrefixLengthxwheremaxPrefixLength=prefixLength0prefixLengthn|ByteString.indexx0==ByteString.indexy0=prefixLength(succn)prefixLengthn=ninstanceRightGCDMonoidByteStringwherecommonSuffixxy=ByteString.dropminNonSuffixLengthxwhereminNonSuffixLength=nonSuffixLength(ByteString.lengthx-1)(ByteString.lengthy-1)nonSuffixLengthmn|ByteString.indexxm==ByteString.indexyn=nonSuffixLength(predm)(predn)nonSuffixLengthmn=m+1instanceGCDMonoidByteString-- Text instancesinstanceLeftCancellativeMonoidTextwheremstripPrefixpt=Text.stripPrefixptinstanceRightCancellativeMonoidTextwheremstripSuffixst=Text.stripSuffixstinstanceCancellativeMonoidTextinstanceLeftGCDMonoidTextwherecommonPrefixxy=maybeText.empty(\(p,_,_)->p)(Text.commonPrefixesxy)instanceRightGCDMonoidTextwherecommonSuffixxy=Text.reverse$commonPrefix(Text.reversex)(Text.reversey)instanceGCDMonoidText