I'm trying to compose F-Algebras like in this page. The difference is that, instead of composing with a tuple, like this:
type FAlgebra[F[_], A] = F[A] => A
def algebraZip[F[_], A, B](fa: FAlgebra[F, A], fb: FAlgebra[F, B])
(implicit F: Functor[F]): FAlgebra[F, (A, B)] =
fab => {
val a = fa(fab.map(_._1))
val b = fb(fab.map(_._2))
(a, b)
}
I would like to use a Seq, like this:
def algebraSeq[F[_], A](fa: FAlgebra[F, A])
(implicit F: Functor[F]): FAlgebra[F, Seq[A]] = ???
Is it possible? What would I need? Or would using shapeless HList help?
If I can make some slight alterations to your constraints, I can find an implementation:
def algebraSeq[F[_]: Traverse, A](fa: FAlgebra[F, A]): FAlgebra[F, Seq[A]] =
fseq => fseq.sequence.map(f => fa(f))
I needed the Traverse instance to be able to sequence a F[Seq[A]] to a Seq[F[A]].
In the past you had to write this function for List instead of Seq because there was no Applicative[Seq] instance. But since cats 2.3.0 instances for immutable.Seq (which is the default scala.Seq in Scala 2.13) were added.
Completely agree with Jasper's answer. But I like to generalise ;)
The shape of your algebra is like CoKleisli:
import cats._
import cats.implicits._
import cats.data.Cokleisli
type FAlgebra[F[_], A] = Cokleisli[F, A, A]
def nestEffect[F[_], A, B, G[_]](coKleisli: Cokleisli[F, A, B])
(implicit F: Traverse[F], G: Applicative[G]): Cokleisli[F, G[A], G[B]] =
Cokleisli((fga: F[G[A]]) => F.sequence[G, A](fga).map(coKleisli.run))
def algebraSeq[F[_], A](fa: FAlgebra[F, A])
(implicit F: Traverse[F]): FAlgebra[F, List[A]] =
nestEffect[F, A, A, List](fa)
Related
I want to map case class Bonus[A: Numeric](amt: A) over a Functor and it fails. The compilation error is
Error:(157, 69) could not find implicit value for evidence parameter of type Numeric[B] (No implicit Ordering defined for B.)
override def fmap[A, B](fa: Bonus[A])(f: A => B): Bonus[B] = Bonus(f(fa.amt))
In general, I want to fix the parameter type in Bonus to numbers. How do I do fix that? Thanks
The code snippet,
trait Functor[F[_]] {
def fmap[A, B](fa: F[A])(f: A => B): F[B]
}
def fmap[A, B, F[_]](fa: F[A])(f: A => B)(implicit ev: Functor[F]): F[B] = ev.fmap(fa)(f)
case class Bonus[A: Numeric](amt: A)
implicit val bonusFunctor = new Functor[Bonus] {
override def fmap[A, B](fa: Bonus[A])(f: A => B): Bonus[B] = Bonus(f(fa.amt)) // error
}
fmap(Bonus(123))(_ * 2)
Update 1
Thank you Mario & Dmytro for your answers.
Dmytro, your answer is precisely as what I found at https://users.scala-lang.org/t/how-to-add-type-constraint-to-functors-map-function/2055. It makes sense that either I drop the constraint or I use a constraint Functor. I accepted Mario's answer because it shows me an alternative solution because it is not possible with Functor.
Instance of Functor type class can be defined not for any type constructor.
The fact that type constructor F[_] has instance of type class Functor means that for any A, B, having a function A => B, you know how to transform F[A] to F[B].
But how to transform Bonus[A] to Bonus[B] for any A, B?
Types Bonus[A], Bonus[B] make sense for any A, B, even if they are not Numeric, but creating new instance of Bonus[B] via constructor makes sense only for B: Numeric.
Either remove context bound Numeric in case class Bonus[A: Numeric](amt: A) or Bonus is not a Functor.
If you define your own type class
trait NumericFunctor[F[_]] {
def fmap[A: Numeric, B: Numeric](fa: F[A])(f: A => B): F[B]
}
it will be not the standard functor over category of types but a custom functor over category of Numeric types.
Try
trait GFunctor[F[_], G[_]] {
def fmap[A, B](fa: F[A])(f: A => B)(implicit ga: G[A], gb: G[B]) : F[B]
}
def fmap[A, B, F[_], G[_]](fa: F[A])(f: A => B)(implicit ev: GFunctor[F, G], ga: G[A], gb: G[B]): F[B] = ev.fmap(fa)(f)
case class Bonus[A: Numeric](amt: A)
implicit val bonusFunctor = new GFunctor[Bonus, Numeric] {
override def fmap[A, B](fa: Bonus[A])(f: A => B)(implicit numA: Numeric[A], numbB: Numeric[B]): Bonus[B] = Bonus(f(fa.amt))
}
fmap(Bonus(123))(_ * 2)
which outputs
res0: Bonus[Int] = Bonus(246)
Note how we have made our typeclass solution aware of further bounds on A and B via
(implicit ga: G[A], gb: G[B])
I am working with cats and I want to transform my val x: State[A, B] to StateT[IO, A, B]. Note: IO is from cats-effects.
How to do this elegantly?
Try mapK in combination with cats.arrow.FunctionK.lift:
x.mapK(lift(IO.eval))
Full compilable code snippet:
import cats.effect.IO
import cats.data.{State, StateT}
import cats.arrow.FunctionK.lift
object InjectIdIO {
def i[S, V](x: State[S, V]): StateT[IO, S, V] = x.mapK(lift(IO.eval))
}
This works because State[S, A] is actually StateT[Eval, S, A], and you want to replace the Eval by IO - this is what the mapK is usually for.
Another alternative with kind-projector:
x.mapK(Lambda[Eval ~> IO](IO.eval(_)))
Try
def liftState[A, B](state: State[A, B]): StateT[IO, A, B] =
StateT[IO, A, B] { s => IO.eval(state.run(s)) }
for example
val x: State[Int, String] = State(int => (int, "foo"))
liftState(x)
Specifically, I'm trying to extend my Functor typeclass with Applicative.
trait Functor[F[_]] {
def fmap[A, B](r: F[A], f: A => B): F[B]
}
object Functor {
implicit class FunctorOps[A, F[_]: Functor](xs: F[A]) {
def fmap[B](f: A => B): F[B] = implicitly[Functor[F]].fmap(xs, f)
}
implicit def SeqFunctor: Functor[Seq] = new Functor[Seq] {
def fmap[A, B](r: Seq[A], f: A => B) = r map f
}
}
trait Applicative[F[_]] extends Functor[F] {
// What I want to do, but this *does not* work.
def fmap[A, B](r: F[A], f: A => B): F[B] = Functor.FunctorOps[A, F](r).fmap(f)
def pure[A](x: A): F[A]
def fapply[A, B](r: F[A], f: F[A => B]): F[B]
}
object Applicative {
implicit class ApplicativeOps[A, F[_]](a: F[A])(implicit F: Applicative[F]) {
def fapply[B](f: F[A => B]): F[B] = F.fapply(a, f)
}
implicit def SeqApplicative: Applicative[Seq] = new Applicative[Seq] {
def pure[A](x: A) = Seq(x)
def fapply[A, B](xs: Seq[A], fs: Seq[A => B]): Seq[B] = xs.flatMap(x => fs.map(_(x)))
}
}
The gist of it is I have to implement fmap for all Applicatives, but it should really be the same method as defined in my FunctorOps class. How do I do this in the cleanest way possible?
You got the Applicative[F] <: Functor[F] part right, but you should really think about what that means. It means that an instance of Applicative[F] also provides the methods for Functor[F]. That is, you can't have both implicit val listFunctor: Functor[List]; implicit val listApplicative: Applicative[List], because then the compiler is confused when you ask for implicit param: Functor[List]. You should only have the latter. What you're trying to do is then nonsensical, because you're defining the Functor instance for F in terms of itself (because the Applicative[F] should be the Functor[F]), and you end up with two Functor[Seq]s regardless.
What you can do is implement fmap in terms of pure and fapply:
trait Applicative[F[_]] extends Functor[F] {
override def fmap[A, B](r: F[A], f: A => B): F[B] = fapply(r, pure(f))
def pure[A](x: A): F[A]
def fapply[A, B](r: F[A], f: F[A => B]): F[B]
}
Then remove the Functor[Seq] instance and keep your Applicative[Seq] the way it is (or override fmap if you want). You have a different problem now, being that implicit search gets a bit turned around, as the Functor[Seq] instance is actually in object Applicative, but fixing implicit resolution is less onerous than enforcing the consistency of separate Functor and Applicative instances. In this case, where Seq is a type whose companion object you cannot control, cats, at least, does something like
package instances {
trait SeqInstances {
implicit val seqFunctor: Functor[Seq] = ???
}
package object seq extends SeqInstances
package object all extends SeqInstances
with AAAInstances
with BBBInstances
with ...
}
FYI: I suggest currying your typeclass methods
def fmap[A, B](r: F[A])(f: A => B): F[B]
def fapply[A, B](r: F[A])(f: F[A => B]): F[B]
and it may be nice to have a flip fapply in ApplicativeOps
def ylppaf[I, B](f: F[I])(implicit ev: A =:= (I => B))
: F[B] = F.fapply(a.fmap(ev))(f)
How can I create a method that takes a generic Collection M[A] and a function from A to B and returns a Collection M[B], using the map method?
Something like:
def convert[A, M[X] <: Traversable[X], B](in: M[A], f: A => B): M[B] =
in.map(f)
The method above fails to compile with: type mismatch; found : Traversable[B] required: M[B]. Since the static type of Traversable[A].map(f: A => B) is Traversable[B] as pointed by Oleg Pyzhcov
Note: The purpose of this method is not just mapping the collection, this is just a simplification.
The full signature of map is
def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That
So you need to provide that CanBuildFrom from the call site and make sure that Repr is inferred to your concrete type M[A] by using collection traits that end on Like and have two type parameters
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
import scala.language.higherKinds
def convert[M[x] <: TraversableLike[x, M[x]], A, B](
in: M[A],
f: A => B
)(implicit
cbf: CanBuildFrom[M[A], B, M[B]]
): M[B] = in.map(f)(cbf)
I am struggling to understand the following function definition in Traverse trait in Scalaz:
def traverse[F[_] : Applicative, A, B](f: A => F[B], t: T[A]): F[T[B]]
The part I don't understand is F[_] : Applicative.
Now, let's see what Applicative is:
trait Applicative[Z[_]] extends Pointed[Z] with Apply[Z] {
override def fmap[A, B](fa: Z[A], f: A => B): Z[B] = this(pure(f), fa)
override def apply[A, B](f: Z[A => B], a: Z[A]): Z[B] = liftA2(f, a, (_:A => B)(_: A))
def liftA2[A, B, C](a: Z[A], b: Z[B], f: (A, B) => C): Z[C] = apply(fmap(a, f.curried), b)
}
Here, for traverse to work for some type F, one needs to bring an implicit object of type Applicative[F] in scope.
I'd like to understand several things:
Wat exactly does F[_] : Applicative mean?
Why does F[_] has something to do with Applicative? We need Applicative[F], not F[something] extends Applicative right?
Why does this method use implicit values of type Applicative[F] without declaring implicit parameters?
I think all three questions can be answered with the fact that this notation:
def traverse[F[_] : Applicative, A, B](f: A => F[B], t: T[A]): F[T[B]]
is equivalent to this:
def traverse[F[_], A, B](f: A => F[B], t: T[A])(implicit $ev: Applicative[F]): F[T[B]]
The first notation is known as a context bound for F[_].