{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Streaming.NonEmpty where

import Control.Category (id, (.))
import Control.Monad (Monad (return))
import Data.Bool (Bool)
import Data.Either
import Data.Eq ((==))
import Data.Function (($))
import Data.Functor (Functor, fmap, (<$>))
import Data.List.NonEmpty hiding (groupBy)
import Data.Semigroup (Semigroup, (<>))
import qualified Data.Semigroup as Semigroup
import Streaming (Of ((:>)), Stream, first, runIdentity, wrap)
import Streaming.Internal
import qualified Streaming.Prelude as S

-- | A stream with at least one functorial layer
newtype NEStream f m a = NEStream (f (Stream f m a)) deriving (a -> NEStream f m b -> NEStream f m a
(a -> b) -> NEStream f m a -> NEStream f m b
(forall a b. (a -> b) -> NEStream f m a -> NEStream f m b)
-> (forall a b. a -> NEStream f m b -> NEStream f m a)
-> Functor (NEStream f m)
forall a b. a -> NEStream f m b -> NEStream f m a
forall a b. (a -> b) -> NEStream f m a -> NEStream f m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
forall (f :: * -> *) (m :: * -> *) a b.
(Monad m, Functor f) =>
a -> NEStream f m b -> NEStream f m a
forall (f :: * -> *) (m :: * -> *) a b.
(Monad m, Functor f) =>
(a -> b) -> NEStream f m a -> NEStream f m b
<$ :: a -> NEStream f m b -> NEStream f m a
$c<$ :: forall (f :: * -> *) (m :: * -> *) a b.
(Monad m, Functor f) =>
a -> NEStream f m b -> NEStream f m a
fmap :: (a -> b) -> NEStream f m a -> NEStream f m b
$cfmap :: forall (f :: * -> *) (m :: * -> *) a b.
(Monad m, Functor f) =>
(a -> b) -> NEStream f m a -> NEStream f m b
Functor)

-- | Is a stream
toStream :: (Functor f, Monad m) => NEStream f m r -> Stream f m r
toStream :: NEStream f m r -> Stream f m r
toStream (NEStream f (Stream f m r)
f) = f (Stream f m r) -> Stream f m r
forall (m :: * -> *) (f :: * -> *) r.
(Monad m, Functor f) =>
f (Stream f m r) -> Stream f m r
wrap f (Stream f m r)
f

-- | fold1 is safe
fold1 :: Monad m => (a -> a -> a) -> NEStream (Of a) m r -> m (Of a r)
fold1 :: (a -> a -> a) -> NEStream (Of a) m r -> m (Of a r)
fold1 a -> a -> a
f (NEStream (a
x :> Stream (Of a) m r
s)) = (a -> a -> a) -> a -> (a -> a) -> Stream (Of a) m r -> m (Of a r)
forall (m :: * -> *) x a b r.
Monad m =>
(x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> m (Of b r)
S.fold a -> a -> a
f a
x a -> a
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id Stream (Of a) m r
s

-- | sconcat as in 'Data.Semigroup', with result
sconcat :: (Semigroup a, Monad m) => NEStream (Of a) m r -> m (Of a r)
sconcat :: NEStream (Of a) m r -> m (Of a r)
sconcat = (a -> a -> a) -> NEStream (Of a) m r -> m (Of a r)
forall (m :: * -> *) a r.
Monad m =>
(a -> a -> a) -> NEStream (Of a) m r -> m (Of a r)
fold1 a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>)

-- | harvest the list with the result
toNonEmpty :: Monad m => NEStream (Of a) m r -> m (Of (NonEmpty a) r)
toNonEmpty :: NEStream (Of a) m r -> m (Of (NonEmpty a) r)
toNonEmpty (NEStream (a
x :> Stream (Of a) m r
r)) = ([a] -> NonEmpty a) -> Of [a] r -> Of (NonEmpty a) r
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (a
x a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:|) (Of [a] r -> Of (NonEmpty a) r)
-> m (Of [a] r) -> m (Of (NonEmpty a) r)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Stream (Of a) m r -> m (Of [a] r)
forall (m :: * -> *) a r.
Monad m =>
Stream (Of a) m r -> m (Of [a] r)
S.toList Stream (Of a) m r
r

-- | harvest the list only
toNonEmpty_ :: Monad m => NEStream (Of a) m r -> m (NonEmpty a)
toNonEmpty_ :: NEStream (Of a) m r -> m (NonEmpty a)
toNonEmpty_ = (Of (NonEmpty a) r -> NonEmpty a)
-> m (Of (NonEmpty a) r) -> m (NonEmpty a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Of (NonEmpty a) r -> NonEmpty a
forall a b. Of a b -> a
S.fst' (m (Of (NonEmpty a) r) -> m (NonEmpty a))
-> (NEStream (Of a) m r -> m (Of (NonEmpty a) r))
-> NEStream (Of a) m r
-> m (NonEmpty a)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NEStream (Of a) m r -> m (Of (NonEmpty a) r)
forall (m :: * -> *) a r.
Monad m =>
NEStream (Of a) m r -> m (Of (NonEmpty a) r)
toNonEmpty

-- | sconcat as in 'Data.Semigroup'
sconcat_ :: (Monad m, Semigroup a) => NEStream (Of a) m r -> m a
sconcat_ :: NEStream (Of a) m r -> m a
sconcat_ (NEStream (a
x :> Stream (Of a) m r
s)) = (a -> a -> a) -> a -> (a -> a) -> Stream (Of a) m r -> m a
forall (m :: * -> *) x a b r.
Monad m =>
(x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> m b
S.fold_ a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>) a
x a -> a
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id Stream (Of a) m r
s

-- | group by some  equality  in non empty groups
groupBy
  :: (Monad m)
  => (a -> a -> Bool)
  -> Stream (Of a) m r
  -> Stream (NEStream (Of a) m) m r
groupBy :: (a -> a -> Bool)
-> Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
groupBy a -> a -> Bool
equals = Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
forall (m :: * -> *) r.
Monad m =>
Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
loop
  where
    loop :: Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
loop Stream (Of a) m r
stream = m (Stream (NEStream (Of a) m) m r)
-> Stream (NEStream (Of a) m) m r
forall (f :: * -> *) (m :: * -> *) r.
m (Stream f m r) -> Stream f m r
Effect (m (Stream (NEStream (Of a) m) m r)
 -> Stream (NEStream (Of a) m) m r)
-> m (Stream (NEStream (Of a) m) m r)
-> Stream (NEStream (Of a) m) m r
forall a b. (a -> b) -> a -> b
$ do
      Either r (a, Stream (Of a) m r)
e <- Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
forall (m :: * -> *) a r.
Monad m =>
Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
S.next Stream (Of a) m r
stream
      Stream (NEStream (Of a) m) m r
-> m (Stream (NEStream (Of a) m) m r)
forall (m :: * -> *) a. Monad m => a -> m a
return (Stream (NEStream (Of a) m) m r
 -> m (Stream (NEStream (Of a) m) m r))
-> Stream (NEStream (Of a) m) m r
-> m (Stream (NEStream (Of a) m) m r)
forall a b. (a -> b) -> a -> b
$ case Either r (a, Stream (Of a) m r)
e of
        Left r
r -> r -> Stream (NEStream (Of a) m) m r
forall (f :: * -> *) (m :: * -> *) r. r -> Stream f m r
Return r
r
        Right (a
a, Stream (Of a) m r
p') ->
          NEStream (Of a) m (Stream (NEStream (Of a) m) m r)
-> Stream (NEStream (Of a) m) m r
forall (f :: * -> *) (m :: * -> *) r.
f (Stream f m r) -> Stream f m r
Step (NEStream (Of a) m (Stream (NEStream (Of a) m) m r)
 -> Stream (NEStream (Of a) m) m r)
-> NEStream (Of a) m (Stream (NEStream (Of a) m) m r)
-> Stream (NEStream (Of a) m) m r
forall a b. (a -> b) -> a -> b
$
            (Stream (Of a) m r -> Stream (NEStream (Of a) m) m r)
-> NEStream (Of a) m (Stream (Of a) m r)
-> NEStream (Of a) m (Stream (NEStream (Of a) m) m r)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
loop (Of a (Stream (Of a) m (Stream (Of a) m r))
-> NEStream (Of a) m (Stream (Of a) m r)
forall (f :: * -> *) (m :: * -> *) a.
f (Stream f m a) -> NEStream f m a
NEStream (a
a a
-> Stream (Of a) m (Stream (Of a) m r)
-> Of a (Stream (Of a) m (Stream (Of a) m r))
forall a b. a -> b -> Of a b
:> (a -> Bool)
-> Stream (Of a) m r -> Stream (Of a) m (Stream (Of a) m r)
forall (m :: * -> *) a r.
Monad m =>
(a -> Bool)
-> Stream (Of a) m r -> Stream (Of a) m (Stream (Of a) m r)
S.span (a -> a -> Bool
equals a
a) Stream (Of a) m r
p'))

-- | what groupBy could be
groupByPure :: (a -> a -> Bool) -> [a] -> [NonEmpty a]
groupByPure :: (a -> a -> Bool) -> [a] -> [NonEmpty a]
groupByPure a -> a -> Bool
equals = Identity [NonEmpty a] -> [NonEmpty a]
forall a. Identity a -> a
runIdentity (Identity [NonEmpty a] -> [NonEmpty a])
-> ([a] -> Identity [NonEmpty a]) -> [a] -> [NonEmpty a]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Stream (Of (NonEmpty a)) Identity () -> Identity [NonEmpty a]
forall (m :: * -> *) a r. Monad m => Stream (Of a) m r -> m [a]
S.toList_ (Stream (Of (NonEmpty a)) Identity () -> Identity [NonEmpty a])
-> ([a] -> Stream (Of (NonEmpty a)) Identity ())
-> [a]
-> Identity [NonEmpty a]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (forall x.
 NEStream (Of a) Identity x -> Identity (Of (NonEmpty a) x))
-> Stream (NEStream (Of a) Identity) Identity ()
-> Stream (Of (NonEmpty a)) Identity ()
forall (m :: * -> *) (f :: * -> *) (g :: * -> *) r.
(Monad m, Functor f) =>
(forall x. f x -> m (g x)) -> Stream f m r -> Stream g m r
S.mapped forall x.
NEStream (Of a) Identity x -> Identity (Of (NonEmpty a) x)
forall (m :: * -> *) a r.
Monad m =>
NEStream (Of a) m r -> m (Of (NonEmpty a) r)
toNonEmpty (Stream (NEStream (Of a) Identity) Identity ()
 -> Stream (Of (NonEmpty a)) Identity ())
-> ([a] -> Stream (NEStream (Of a) Identity) Identity ())
-> [a]
-> Stream (Of (NonEmpty a)) Identity ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> a -> Bool)
-> Stream (Of a) Identity ()
-> Stream (NEStream (Of a) Identity) Identity ()
forall (m :: * -> *) a r.
Monad m =>
(a -> a -> Bool)
-> Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
groupBy a -> a -> Bool
equals (Stream (Of a) Identity ()
 -> Stream (NEStream (Of a) Identity) Identity ())
-> ([a] -> Stream (Of a) Identity ())
-> [a]
-> Stream (NEStream (Of a) Identity) Identity ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [a] -> Stream (Of a) Identity ()
forall (m :: * -> *) (f :: * -> *) a.
(Monad m, Foldable f) =>
f a -> Stream (Of a) m ()
S.each

-- | collapse semigroups by some equality
groupSemigroupBy :: (Semigroup a, Monad m) => (a -> a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m r
groupSemigroupBy :: (a -> a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m r
groupSemigroupBy a -> a -> Bool
f = (forall x. NEStream (Of a) m x -> m (Of a x))
-> Stream (NEStream (Of a) m) m r -> Stream (Of a) m r
forall (m :: * -> *) (f :: * -> *) (g :: * -> *) r.
(Monad m, Functor f) =>
(forall x. f x -> m (g x)) -> Stream f m r -> Stream g m r
S.mapped forall x. NEStream (Of a) m x -> m (Of a x)
forall a (m :: * -> *) r.
(Semigroup a, Monad m) =>
NEStream (Of a) m r -> m (Of a r)
sconcat (Stream (NEStream (Of a) m) m r -> Stream (Of a) m r)
-> (Stream (Of a) m r -> Stream (NEStream (Of a) m) m r)
-> Stream (Of a) m r
-> Stream (Of a) m r
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> a -> Bool)
-> Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
forall (m :: * -> *) a r.
Monad m =>
(a -> a -> Bool)
-> Stream (Of a) m r -> Stream (NEStream (Of a) m) m r
groupBy a -> a -> Bool
f

-- | what should be possible to do with 'groupBy'
-- fmap sconcat . groupBy equals
groupSemigroupByPure :: Semigroup b => (b -> b -> Bool) -> [b] -> [b]
groupSemigroupByPure :: (b -> b -> Bool) -> [b] -> [b]
groupSemigroupByPure b -> b -> Bool
equals = Identity [b] -> [b]
forall a. Identity a -> a
runIdentity (Identity [b] -> [b]) -> ([b] -> Identity [b]) -> [b] -> [b]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Stream (Of b) Identity () -> Identity [b]
forall (m :: * -> *) a r. Monad m => Stream (Of a) m r -> m [a]
S.toList_ (Stream (Of b) Identity () -> Identity [b])
-> ([b] -> Stream (Of b) Identity ()) -> [b] -> Identity [b]
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (b -> b -> Bool)
-> Stream (Of b) Identity () -> Stream (Of b) Identity ()
forall a (m :: * -> *) r.
(Semigroup a, Monad m) =>
(a -> a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m r
groupSemigroupBy b -> b -> Bool
equals (Stream (Of b) Identity () -> Stream (Of b) Identity ())
-> ([b] -> Stream (Of b) Identity ())
-> [b]
-> Stream (Of b) Identity ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [b] -> Stream (Of b) Identity ()
forall (m :: * -> *) (f :: * -> *) a.
(Monad m, Foldable f) =>
f a -> Stream (Of a) m ()
S.each