Skip to content

Applicative versus TeeWith - different behaviour? #3174

@drshade

Description

@drshade

Hi There

Thanks for building a great streaming library :)

Please see the below example - I was surprised that it seems like when using applicative for executing a fold, the original stream is re-used? As opposed to using using teeWith which makes a copy.

Is this correct behaviour for Functor/Applicative? I would expect that each leg of the applicative has no effect on the others, but that doesn't seem to be the case. It seems like the first Fold.filter consumes the stream, leaving an empty stream for the second Fold.filter.

See my very small example below:

data Processed = Processed { short :: Int, long :: Int } deriving Show

process1 :: Fold.Fold IO Text Processed
process1 =
    Processed
        <$> Fold.filter (( < 5) . length) Fold.length
        <*> Fold.filter ((>= 5) . length) Fold.length

process2 :: Fold.Fold IO Text Processed
process2 =
    Fold.teeWith
        Processed
        (Fold.filter (( < 5) . length) Fold.length)
        (Fold.filter ((>= 5) . length) Fold.length)

test :: IO ()
test = do
    result1 <- Stream.fromList input & Stream.fold process1
    result2 <- Stream.fromList input & Stream.fold process2
    print result1
    print result2
    where input = ["hello", "world", "cabbage", "cat"]

Outputs:

Processed {short = 1, long = 0}
Processed {short = 1, long = 3}

Is this a bug or expected behaviour?

All the best
Tom

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions