I'm trying to learn functional random from cats. This is method inside big class:
def prepareDate(order: Model, zoneId: String): F[Instant] =
Random[F].betweenLong(7200, 21600).flatMap { seconds =>
order.dateTime
.plusSeconds(seconds)
.toInstant(ZoneOffset.of(zoneId))
.asInstanceOf[F[Instant]]
}
it not compiles with No given instance of type cats.effect.std.Random[F] was found for parameter ev of method apply in object Random.
error
I've tried to put Random inside this way:
class SomeClass[F[_]: Async: Logger: Random]
but have no idea how to implicit it in object-companion.
Let's remove some of the fluff, since the logic itself is irrelevant for the problem:
So... What's
F[_]
? Compiler will ask you the same question.If you had some concrete instance of
F[_]
, for examplecats.IO
, then the whole thing would be simple. You would just need to obtain an instance ofRandom[IO]
to work with, which can be done with e.g.Random.scalaUtilRandom[IO]
(this gives anIO[Random[IO]]
hence theflatMap
):So what your question really comes down to is - given that you don't know what the user of
prepareDate
will be using asF[_]
(it could beIO
or something else), how do you intend to prove that there will be aRandom[F]
available in scope?Your
F[_]
is probably a generic parameter in the context where yourprepareDate
method is defined. In case it's a class, then what you wrote would be correct -class SomeClass[F[_]: Random]
means thatF
has to be a higher-kinded type (due to[_]
) and there has to be aRandom[F]
available in scope. Whoever is instantiating a concrete instance ofSomeClass
with some concreteF[_]
will have to make sure thatRandom[F]
is in scope.Here's some complete code:
You mentioned having a companion object, but that doesn't change much in the concept itself - you just move "I need some
F[_]
that has aRandom[F]
in scope" from your class definition, to your method definition:Btw in case it helps you or someone else:
[F[_] : Random]
is just syntactic sugar for the implicit parameter of type[Random[F]]
. This works equally fine, it's just more verbose: