Skip to content

Interleave effects better in chunksOf #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

treeowl
Copy link
Contributor

@treeowl treeowl commented Apr 17, 2018

Generalize the type of chunksOf to allow the inner and outer
streams of the result to use different underlying monads. This
forces effects to be handled within the inner monad, leading
to an arguably better sort of chunking.

Fixes #45

Generalize the type of `chunksOf` to allow the inner and outer
streams of the result to use different underlying monads. This
forces effects to be handled within the inner monad, leading
to an arguably better sort of chunking.

Fixes haskell-streaming#45
@treeowl
Copy link
Contributor Author

treeowl commented Apr 19, 2018

@andrewthad, do you think you could weigh in on this? Is there any reason to prefer the old semantics? Is there any potential performance gotcha here?

@treeowl
Copy link
Contributor Author

treeowl commented Apr 19, 2018

Ah, I see the weakness now, @torgeirsh. As far as I can tell, this version will/can turn the empty stream into a stream producing the empty stream, instead of just an empty stream. I have the feeling there might also be ways to get evenly divided streams to end up with empty end bits. I suspect users will be surprised by this. The trouble is that this commits to producing a functor layer before knowing if the stream is finished.

@andrewthad
Copy link
Contributor

I agree that turning the empty stream into a stream containing the empty stream is non-intuitive here. But, I really like that the new definition clearly separates the effectful inner stream from the non-effectful outer one.

@andrewthad
Copy link
Contributor

I have the feeling there might also be ways to get evenly divided streams to end up with empty end bits.

I suspect otherwise. Part of the promise of the streaming api is that return () should be indistinguishable from lift (return ()). I think that a function with the behavior you describe would distinguish these two.

Copy link
Contributor

@andrewthad andrewthad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that, despite small differences in behavior, this is better than the current implementation of chunksOf and should replace it.

@treeowl
Copy link
Contributor Author

treeowl commented Apr 19, 2018 via email

@torgeirsh
Copy link
Contributor

This is indeed an unfortunate side effect. However, I think it can be solved by using the internal API instead of the external one. This is a quick proof of concept hack:

chunksOf'' :: (Functor f, Monad m, Monad m0) => Int -> Stream f m r -> Stream (Stream f m) m0 r
chunksOf'' n = go where
	go s = case s of
		S.Return r -> pure r
		_ -> do
			stage <- S.yields $ lift . S.inspect =<< S.splitsAt n s
			case stage of
				Left r -> pure r
				Right s' -> go $ S.wrap s'

Does it make sense? I'll try to rewrite the rest in terms of the internal API.

@treeowl
Copy link
Contributor Author

treeowl commented Apr 19, 2018

@torgeirsh, no, I do not think that makes sense. As @andrewthad mentioned, we need to be careful to treat lift (return r) the same as return r.

@torgeirsh
Copy link
Contributor

I see, when pattern matching Effect, a Step is required in order to bind it of course. Seems awkward at first, but I agree there's no other way.

@treeowl
Copy link
Contributor Author

treeowl commented Apr 19, 2018 via email

@torgeirsh
Copy link
Contributor

Hmm, I wonder if there should be some kind of policy for this? It might be confusing to have a mix of functions with effectful and pure outer streams.

@treeowl
Copy link
Contributor Author

treeowl commented May 2, 2018

Yes, there certainly should be. I'm wondering whether @Gabriel439, @snoyberg, or @ekmett have any thoughts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants