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

Writer can be covariant? #4630

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

windymelt
Copy link

I found Writer[L, V] is currently invariant.

final case class WriterT[F[_], L, V](run: F[(L, V)]) {

Can it be covariant?

  • ZIO
    • This is not code itself, but they accepts treating Writer as covariant.
  • Scalaz
    • Currently not treating Writer as covariant.
  • Meanwhile, Reader[-R, A] is contra-variant on parameter R in Cats.

I'm newbie to contribute Cats, so any editing/closing is welcome.

Example that we want covariance for Writer

import cats.data.Writer
type Words[A] = Writer[List[String], A]

trait LongCat[F[_]]:
  def the: F["the"]
  def long(expr: F["the" | "long"]): F["long"]
  def cat(expr: F["long"]): F["cat"]
end LongCat

object LongCatImpl extends LongCat[Words]:
  def the: Words["the"] = Writer(List("the"), "the")
  def long(expr: Words["the" | "long"]): Words["long"] =
    expr.mapBoth((l, v) => ("long" :: l, "long"))
  def cat(expr: Words["long"]): Words["cat"] =
    expr.mapBoth((l, v) => ("cat" :: l, "cat"))
end LongCatImpl

locally:
  import LongCatImpl.*
  val repr = cat(long(long(the)))
  // => Found:    Words[("the" : String)]
  //    Required: Words[("the" : String) | ("long" : String)] 
  println(repr.run._1.reverse) // What I want: "the" :: "long" :: "long" :: "cat" :: Nil

@johnynek
Copy link
Contributor

It can't be covariant, because we don't know anything about F[_]. We could require F[+_] which would allow it to be covariant, but that was not done.

that said, note that def widen[B >: A]: F[B] exists on Functor[F] and internally that can always be implemented by returning the same item (or at worst a safe cast due to the functor laws). So, you should be able to do fa.widen when you need covariance.

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.

2 participants