cats-effect
cats-effect copied to clipboard
Laws testing for queue functor instances
We have {Functor, Invariant, Contravariant}
instances for {Q, Deq, PQ}ueue
in cats.effect.std
but they currently have no laws tests. We should correct this :)
I'll try to add this during the next week
I'll try to add this during the next week
Awesome, thanks!! :)
Started fiddling with it, and already have a couple of questions. Maybe you guys could help me with direction.
First, for law-tests I need Eq[Queue[F, A]]
instance. I suppose I can derive it by taking all elements from Q/Deq/PQueue and comparing the lists. Does that make sense here?
Second, I need a Gen
instance for Queue[F, A]
and I suppose that I want to generate real instances - Bounded, Unbounded, Dropping, CircullarBuffer. Creation of these is effectful (cuz of Ref) and I'm ending up with Gen[IO[Queue[IO, A]]]
and don't know how to solve this.
Started fiddling with it, and already have a couple of questions. Maybe you guys could help me with direction.
First, for law-tests I need
Eq[Queue[F, A]]
instance. I suppose I can derive it by taking all elements from Q/Deq/PQueue and comparing the lists. Does that make sense here?Second, I need a
Gen
instance forQueue[F, A]
and I suppose that I want to generate real instances - Bounded, Unbounded, Dropping, CircullarBuffer. Creation of these is effectful (cuz of Ref) and I'm ending up withGen[IO[Queue[IO, A]]]
and don't know how to solve this.
Excellent questions! I think for laws/property testing we at some point have to depend on unsafeRun
. If you've looked at TestInstances
you may have already seen that we have
implicit def eqIOA[A: Eq](implicit ticker: Ticker): Eq[IO[A]] =
Eq.by(unsafeRun(_))
so I think you can piggy-back on this to get
//loop with tryTake until you get None
def toList[A](q: Queue[IO, A]): IO[List[A]] = ???
implicit def eqForQueue[A: Eq]: Eq[Queue[IO, A]] = Eq.by(q => toList(q))
As for Gen
, I think I'd be inclined to pull a similar trick:
def fromList[A](as: List[A]): IO[Queue[IO, A]] = Queue.empty[IO, A].flatMap(q => as.traverse(a => q.offer(a)))
def genQueue[A: Arbitrary]: Gen[Queue[IO, A]] =
arbitrary[List[A]].map(as => fromList(as).unsafeRunSync())
Does that make sense? Of course someone else might have a better idea! 😂
Thank you! Managed to make it work 🙂
@patseev I don't think I noticed a PR connected to this issue. Since it sounds like you got it to work, would you be interested in submitting a PR? Thanks! :)