Skip to content

Instantly share code, notes, and snippets.

@rossabaker
Created February 5, 2022 04:37
Show Gist options
  • Save rossabaker/2f50e77cecc6afd096dd7895f763b5f6 to your computer and use it in GitHub Desktop.
Save rossabaker/2f50e77cecc6afd096dd7895f763b5f6 to your computer and use it in GitHub Desktop.
Set is not a functor
scala> import org.typelevel.ci._
import org.typelevel.ci._
scala> val f: String => CIString = CIString.apply
val f: String => org.typelevel.ci.CIString = $Lambda$1025/2055291664@4bbf38b8
scala> val g: CIString => String = _.toString
val g: org.typelevel.ci.CIString => String = $Lambda$1027/1152113439@62108cd3
scala> val rosses = Set("Ross", "ROSS", "ross") // three too many if you ask me
val rosses: scala.collection.immutable.Set[String] = Set(Ross, ROSS, ross)
scala> rosses.map(f).map(g)
val res0: scala.collection.immutable.Set[String] = Set(Ross)
scala> rosses.map(f andThen g)
val res1: scala.collection.immutable.Set[String] = Set(Ross, ROSS, ross)
@rossabaker
Copy link
Author

I don't know about "tricky". CIString satisfies the contract of .equals. There's no substitution law. cats.Eq doesn't have one either. Haskell's Eq recently added it as an "expectation", but officially has no laws. We should strongly prefer that property, but it's neither illegal nor unusual to break it. A couple more examples:

  • (s: Set[A] => s.toList) (ordering is undefined)
  • (d: Double) => 1.0 / d (try it with 0.0 and -0.0)

A set whose equivalence relation guarantees substitution is a functor, but Scala's Set doesn't, so it's not.

@philipschwarz
Copy link

Noted. Thank you.

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