module Numeric.Addition.Partitionable
(
Partitionable(..)
) where
import Prelude ((),Bool(..),($),id,(>>=))
import Numeric.Semigroup.Additive
import Numeric.Natural
import Data.List.NonEmpty (NonEmpty(..), fromList)
concat :: NonEmpty (NonEmpty a) -> NonEmpty a
concat m = m >>= id
class Additive m => Partitionable m where
partitionWith :: (m -> m -> r) -> m -> NonEmpty r
instance Partitionable Bool where
partitionWith f False = f False False :| []
partitionWith f True = f False True :| [f True False, f True True]
instance Partitionable Natural where
partitionWith f n = fromList [ f k (n k) | k <- [0..n] ]
instance Partitionable () where
partitionWith f () = f () () :| []
instance (Partitionable a, Partitionable b) => Partitionable (a,b) where
partitionWith f (a,b) = concat $ partitionWith (\ax ay ->
partitionWith (\bx by -> f (ax,bx) (ay,by)) b) a
instance (Partitionable a, Partitionable b, Partitionable c) => Partitionable (a,b,c) where
partitionWith f (a,b,c) = concat $ partitionWith (\ax ay ->
concat $ partitionWith (\bx by ->
partitionWith (\cx cy -> f (ax,bx,cx) (ay,by,cy)) c) b) a
instance (Partitionable a, Partitionable b, Partitionable c,Partitionable d ) => Partitionable (a,b,c,d) where
partitionWith f (a,b,c,d) = concat $ partitionWith (\ax ay ->
concat $ partitionWith (\bx by ->
concat $ partitionWith (\cx cy ->
partitionWith (\dx dy -> f (ax,bx,cx,dx) (ay,by,cy,dy)) d) c) b) a
instance (Partitionable a, Partitionable b, Partitionable c,Partitionable d, Partitionable e) => Partitionable (a,b,c,d,e) where
partitionWith f (a,b,c,d,e) = concat $ partitionWith (\ax ay ->
concat $ partitionWith (\bx by ->
concat $ partitionWith (\cx cy ->
concat $ partitionWith (\dx dy ->
partitionWith (\ex ey -> f (ax,bx,cx,dx,ex) (ay,by,cy,dy,ey)) e) d) c) b) a