moduleNumeric.Algebra.Factorable(-- * Factorable Multiplicative SemigroupsFactorable(..))whereimportData.List.NonEmptyimportNumeric.Algebra.Class(Multiplicative(..))importPreludehiding(concat)-- | `factorWith f c` returns a non-empty list containing `f a b` for all `a, b` such that `a * b = c`.---- Results of factorWith f 0 are undefined and may result in either an error or an infinite list.classMultiplicativem=>FactorablemwherefactorWith::(m->m->r)->m->NonEmptyrinstanceFactorableBoolwherefactorWithfFalse=fFalseFalse:|[fFalseTrue,fTrueFalse]factorWithfTrue=fTrueTrue:|[]instanceFactorable()wherefactorWithf()=f()():|[]concat::NonEmpty(NonEmptya)->NonEmptyaconcatm=m>>=idinstance(Factorablea,Factorableb)=>Factorable(a,b)wherefactorWithf(a,b)=concat$factorWith(\axay->factorWith(\bxby->f(ax,bx)(ay,by))b)ainstance(Factorablea,Factorableb,Factorablec)=>Factorable(a,b,c)wherefactorWithf(a,b,c)=concat$factorWith(\axay->concat$factorWith(\bxby->factorWith(\cxcy->f(ax,bx,cx)(ay,by,cy))c)b)ainstance(Factorablea,Factorableb,Factorablec,Factorabled)=>Factorable(a,b,c,d)wherefactorWithf(a,b,c,d)=concat$factorWith(\axay->concat$factorWith(\bxby->concat$factorWith(\cxcy->factorWith(\dxdy->f(ax,bx,cx,dx)(ay,by,cy,dy))d)c)b)ainstance(Factorablea,Factorableb,Factorablec,Factorabled,Factorablee)=>Factorable(a,b,c,d,e)wherefactorWithf(a,b,c,d,e)=concat$factorWith(\axay->concat$factorWith(\bxby->concat$factorWith(\cxcy->concat$factorWith(\dxdy->factorWith(\exey->f(ax,bx,cx,dx,ex)(ay,by,cy,dy,ey))e)d)c)b)a