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

SignallingRef has to be upcast to Signal for syntax #40

Open
armanbilge opened this issue May 10, 2022 · 4 comments
Open

SignallingRef has to be upcast to Signal for syntax #40

armanbilge opened this issue May 10, 2022 · 4 comments
Labels
UX Improve usability of an existing feature

Comments

@armanbilge
Copy link
Owner

This is annoying.

@armanbilge armanbilge added the bug Something isn't working label May 10, 2022
@2chilled
Copy link
Collaborator

This should be fixed by #183 shouldn't it?

@armanbilge
Copy link
Owner Author

Unfortunately not, this is really an FS2 issue.

//> using lib "co.fs2::fs2-core::3.6.1"

import cats.effect.IO
import cats.syntax.all.*
import fs2.concurrent.{Signal, SignallingRef}

def sigRef: SignallingRef[IO, String] = ???

@main def main =

  (sigRef: Signal[IO, String]).void

  sigRef.void
[error] ./signal.scala:13:3: value void is not a member of fs2.concurrent.SignallingRef[cats.effect.IO, String].
[error] An extension method was tried, but could not be fully constructed:
[error] 
[error]     cats.syntax.all.toFunctorOps[
[error]       ([A] =>> fs2.concurrent.SignallingRef[cats.effect.IO, A])
[error]     , String](sigRef)(cats.Invariant.catsApplicativeForArrow[F, A])
[error]   sigRef.void
[error]   ^^^^^^^^^^^
Error compiling project (Scala 3.2.2, JVM)
Compilation failed

But, I just had an idea how to fix it :)

@armanbilge
Copy link
Owner Author

But, I just had an idea how to fix it :)

Erm, spoke too soon :) I thought the problem is in FS2, but it's not really. You can't have a Functor for SignallingRef, so the implicit search gives up quickly and with good reason.

So it turns out, this is something that would need to be fixed in Cats 😂 the question is, if you have Foo[A] <: Bar[A], and Bar implements Functor but Foo does not, should you be able to use functor syntax on Foo? All the methods would return Bar in that case.

I have a hard time imagining such a major change like that being made in Cats.

That said, maybe the fix is to add an .asSignal method to SignallingRef in FS2 /shrug

@armanbilge
Copy link
Owner Author

armanbilge commented Feb 11, 2023

One more datapoint: experimented with the extension-based encoding in Scala 3, and it doesn't work there either. That's even harder to fix than the implicit class syntax used in Scala 2. So I don't really think we can "fix" this, we can just make the upcast more convenient.

Edit: Ha wait, totally screwed that up. It does work! So that's very interesting 🤔

trait Functor[F[_]]:
  extension [A](fa: F[A]) def map[B](f: A => B): F[B]

trait Foo[A]
object Foo:
  given Functor[Foo] = ???

trait Bar[A] extends Foo[A]

def foo: Foo[String] = ???
def bar: Bar[String] = ???

@main def main =
  foo.map(_.length)
  bar.map(_.length)

@armanbilge armanbilge added UX Improve usability of an existing feature and removed bug Something isn't working labels Feb 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
UX Improve usability of an existing feature
Projects
None yet
Development

No branches or pull requests

2 participants