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 partial folding methods to Foldable #2322

Closed
LukaJCB opened this issue Jul 10, 2018 · 13 comments · Fixed by #2452
Closed

Add partial folding methods to Foldable #2322

LukaJCB opened this issue Jul 10, 2018 · 13 comments · Fixed by #2452

Comments

@LukaJCB
Copy link
Member

LukaJCB commented Jul 10, 2018

We can define functions that only tear down a subset of the structure by using something like a PartialFunction or Option to exclude individual elements from the aggregation.
E.g.:

def filterFold[A, M: Monoid](fa: F[A])(f: A => Option[M]): M =
  foldLeft(fa, Monoid[M].empty)((acc, cur) => f(cur) match {
    case Some(m) => acc |+| m
    case _ => acc
  })

def collectFold[A, M: Monoid](fa: F[A])(f: PartialFunction[A, M]): M =
   foldLeft(fa, Monoid[M].empty)((acc, cur) => acc |+| f.applyOrElse(cur, _ => Monoid[M].empty))

These should be equivalent to collect(f).fold and filter(f).fold respectively, so we could add some laws for that.

@kun-song
Copy link
Contributor

Let me give it a try :)

@LukaJCB
Copy link
Member Author

LukaJCB commented Jul 10, 2018

Go ahead :)

@peterneyens
Copy link
Collaborator

I wonder in what way this relates to FunctorFilter and TraverseFilter that were moved to cats-mtl ( FunctorEmpty and TraverseEmpty).

@LukaJCB
Copy link
Member Author

LukaJCB commented Jul 11, 2018

They're related in a sense, but you can use these on something like NonEmptyList as well, since it tears down the structure and has no requirement for containing an empty element.

@denisrosca
Copy link
Contributor

@LukaJCB afaict Foldable doesn't have collect and filter defined so I'm not sure how the laws you propose would be implemented?

@LukaJCB
Copy link
Member Author

LukaJCB commented Jul 19, 2018

@denisrosca they'd have to be implemented on FunctorEmpty in cats-mtl, though I guess we could formulate some different laws, i.e. by using toList or using some other properties:

For example:

forAll  { (fa: F[A], f: A => Boolean) =>
  fa.forall(f) <-> (fa.filterFold(a => if (f(a)) Some(a) else None) === fa.combineAll)
}

@LukaJCB
Copy link
Member Author

LukaJCB commented Aug 14, 2018

@satansk Have you had a shot at this? Are you blocked by something? Is it something I could help with? :)

@kun-song
Copy link
Contributor

@LukaJCB thanks, and yes, I did encounter a problem, I can't import the project into intellij idea, and here is the error message:

[error] coursier.ResolutionException: Encountered 5 error(s) in dependency resolution:
[error]     org.scala-native:nativelib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/nativelib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:test-interface_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/test-interface_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:scalalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/scalalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:auxlib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/auxlib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:javalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/javalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error] coursier.ResolutionException: Encountered 5 error(s) in dependency resolution:
[error]     org.scala-native:nativelib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/nativelib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:test-interface_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/test-interface_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:scalalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/scalalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:auxlib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/auxlib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:javalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/javalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error] (kernelNative / coursierResolutions) coursier.ResolutionException: Encountered 5 error(s) in dependency resolution:
[error]     org.scala-native:nativelib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/nativelib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:test-interface_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/test-interface_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:scalalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/scalalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:auxlib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/auxlib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:javalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/javalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error] (kernelNative / ssExtractDependencies) coursier.ResolutionException: Encountered 5 error(s) in dependency resolution:
[error]     org.scala-native:nativelib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/nativelib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/nativelib_native0.3_2.12/0.3.7/nativelib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:test-interface_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/test-interface_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/test-interface_native0.3_2.12/0.3.7/test-interface_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:scalalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/scalalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/scalalib_native0.3_2.12/0.3.7/scalalib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:auxlib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/auxlib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/auxlib_native0.3_2.12/0.3.7/auxlib_native0.3_2.12-0.3.7.pom
[error]     org.scala-native:javalib_native0.3_2.12:0.3.7:
[error]         not found:
[error]             /Users/satansk/.ivy2/local/org.scala-native/javalib_native0.3_2.12/0.3.7/ivys/ivy.xml
[error]             https://repo1.maven.org/maven2/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/releases/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error]             https://oss.sonatype.org/content/repositories/snapshots/org/scala-native/javalib_native0.3_2.12/0.3.7/javalib_native0.3_2.12-0.3.7.pom
[error] Total time: 439 s, completed Aug 15, 2018 11:46:10 PM
[info] shutting down server

And I found @LukaszMarchewka had encountered the same problem: #2382, maybe this can be solved by some sbt settings?

@LukaszMarchewka
Copy link
Contributor

@satansk I have had exactly the same problem, #2382 fixes this.

@LukaJCB
Copy link
Member Author

LukaJCB commented Aug 16, 2018

I'm sorry that this seems to make it hard for IntelliJ users :(
For now maybe you can just manually use @LukaszMarchewka workaround before it's merged hopefully soon.

@LukaJCB LukaJCB modified the milestone: 1.3 Aug 16, 2018
@kun-song
Copy link
Contributor

@LukaszMarchewka thanks, it did work :)

@kun-song
Copy link
Contributor

kun-song commented Sep 1, 2018

Hi @LukaJCB , I have added the methods, and I want to add unit test like bellow:

  test(s"Foldable[$name] partial summation") {
    forAll { (fa: F[Int], f: Int  Boolean) 
      val pf: PartialFunction[Int, Int] = {
        case n if f(n)  n
      }
      fa.filterFold(a  if (f(a)) Some(a) else None) should === fa.collectFold(f)
    }
  }

I think I should add some syntax to support this, should I add them to foldable or some other places?

And it seems that the syntax for filterFold has already be defined, but I just can't find it, so I just add a collectFold syntax.

Thanks a lot :)

@kun-song
Copy link
Contributor

kun-song commented Sep 1, 2018

Finally, I use the following properties using toList:

    forAll { (fa: F[Int], f: Int  Boolean) 
      val m: Monoid[Int] = Monoid[Int]

      val pf: PartialFunction[Int, Int] = {
        case n if f(n)  n
      }
      fa.collectFold(pf) should === (fa.toList.collect(pf).fold(m.empty)(m.combine))

      def g(a: Int): Option[Int] = Some(a).filter(f)
      fa.filterFold(g) should === (fa.toList.filter(f).fold(m.empty)(m.combine))
    }

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

Successfully merging a pull request may close this issue.

5 participants