Skip to content
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

Add foldMap alternative that uses scan, scanMonoid #1184

Closed
kubukoz opened this issue Jul 23, 2018 · 7 comments
Closed

Add foldMap alternative that uses scan, scanMonoid #1184

kubukoz opened this issue Jul 23, 2018 · 7 comments
Labels

Comments

@kubukoz
Copy link
Member

kubukoz commented Jul 23, 2018

Something along the lines of:

def scanMap[O2](f: (O2, O) => F[O2])(implicit O2: Monoid[O2], F: Functor[F]): fs2.Stream[F, O2] =
  stream.evalScan(O2.empty)((acc, el) => F.map(f(acc, el))(O2.combine(acc, _)))

Not sure about the naming of it, could be evalScanMonoid or something like that, but it looks similar to foldMap to me (apart from the Functor[F] requirement). Maybe it's possible to write it with pull and without the Functor bound?

Also, scanMonoid resembling foldMonoid:

def scanMonoid(implicit O: Monoid[O]): fs2.Stream[F, O]
@kubukoz
Copy link
Member Author

kubukoz commented Jul 23, 2018

As mentioned in the gitter channel, I'll gladly implement these ;)

@mpilquist mpilquist added this to the 1.0 milestone Jul 27, 2018
@mpilquist
Copy link
Member

@kubukoz Do you still want to implement these? The signatures look good to me.

@kubukoz
Copy link
Member Author

kubukoz commented Sep 6, 2018 via email

@mpilquist
Copy link
Member

Sounds good to me. Looking forward to it.

@kubukoz
Copy link
Member Author

kubukoz commented Sep 11, 2018

I'm on it! Should be done this week. I saw that scanMap is already a thing in 1.0, but in a slightly different form.

What I'd be looking for now is:

def evalScanMonoid[F2[x] >: F[x], O2](f: O => F2[O2])(implicit O2: Monoid[O2],
                                                        F: Functor[F2]): Stream[F2, O2] =
  evalScan[F2, O2](O2.empty) { (acc, o) =>
    f(o).map(O2.combine(acc, _))
  }

Maybe def scanMap[O2](f: (O2, O) => F[O2])(implicit O2: Monoid[O2], F: Functor[F]) is also a good thing to have though, in which case the evalScanMonoid could be implemented in terms of that.

Edit: Now that I think about it, I think having the (f: (O2, O) => F[O2])(implicit O2: Monoid[O2], F: Functor[F]) variant would be confusing - since the O2 value passed to f would still be combined with the result of f, but could also be used in f itself. If someone wants that level of control, it might be better for them to call evalScan directly.

@mpilquist mpilquist modified the milestones: 1.0, Later Dec 3, 2018
@tabdulradi
Copy link
Contributor

tabdulradi commented Jan 15, 2019

I saw that scanMap is already a thing in 1.0, but in a slightly different form.

I couldn't find that method in the code base, only from old commits from 2013, seems it didn't make it at the end. So I defined it myself like:

    def scanMap[O2](f: O => O2)(implicit O2: Monoid[O2]): Stream[F, O2] =
      self.scan(O2.empty)((acc, el) => acc |+| f(el))

    def scanMonoid(implicit O: Monoid[O]): Stream[F, O] =
      self.scanMap(identity)

Happy to PR the snippet above if it's useful to others.

@mpilquist
Copy link
Member

@tabdulradi Sounds good, PR is definitely welcome!

@mpilquist mpilquist removed this from the Later milestone Sep 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants