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)
Related
let's say I have:
trait Get[F[_], A, B]{
def get(a:A): F[B]
}
I want to be able to map over the result type B, ie I want to be able to do:
val getFoo: Get[IO, String, Foo] = ???
val foo2Bar: Foo => Bar = ???
val getBar: Get[IO, String, Bar] = getFoo.map(foo2Bar)
I understand that I should implement a Functor instance for Get but I am struggling as I don't know what type signature to use.
I tried the following:
implicit val functor:Functor[Get] = ???
implicit val functor: Functor[Lambda[(F[_], K, A) => Get[F, K, A]]] = ???
but they don't seem to be of the right type as I can't seem to use the functor syntax extension as illustrated at the top. What is the right way of expressing the type here? What would be the equivalent type be if I use the kind-projector plugin?
Try
import cats.syntax.functor._
implicit def functor[F[_]: Functor, A]: Functor[Get[F, A, ?]] = new Functor[Get[F, A, ?]] {
override def map[B, B1](fa: Get[F, A, B])(f: B => B1): Get[F, A, B1] = a => fa.get(a).map(f)
}
I often find myself having to perform what is pretty much the same operation on both a value and also a functor of that value. I usually achieve this with two implicit classes, like this:
implicit class Apimped(a: A) {
def doSomething: B = ???
}
implicit class FApimped[F[_]: Functor](fa: F[A]) {
def doSomething: F[B] = Functor[F].map(fa)(a => a.doSomething)
}
So then I can do this, for example:
a.doSomething //B
Option(a).doSomething //Option[B]
However, it seems a bit unwieldy having to write two implicit classes (often for each value type) to do this. My question is, is there anyway to achieve the above with only a single implicit class? That is, the map operation would be implicit in cases when you call doSomething on a functor of the value. Thanks.
I don't know whether it's in Scalaz/Cats (maybe, cannot guarantee that it's not there), but in principle, it does work. Here is a little demo without any dependencies that demonstrates the principle.
Assume you have these typeclasses from either Scalaz or Cats:
import scala.language.higherKinds
trait Functor[F[_]] {
def map[A, B](a: F[A])(f: A => B): F[B]
}
type Id[X] = X
implicit object IdFunctor extends Functor[Id] {
def map[A, B](a: A)(f: A => B): B = f(a)
}
implicit object OptionFunctor extends Functor[Option] {
def map[A, B](a: Option[A])(f: A => B) = a map f
}
you can then either write or find in the library a typeclass that works like the following contraption:
trait EverythingIsAlwaysAFunctor[A, B, F[_]] {
def apply(a: A): F[B]
def functor: Functor[F]
}
object EverythingIsAlwaysAFunctor {
implicit def functorIsFunctor[A, F[_]](implicit f: Functor[F])
: EverythingIsAlwaysAFunctor[F[A], A, F] = {
new EverythingIsAlwaysAFunctor[F[A], A, F] {
def apply(fa: F[A]): F[A] = fa
def functor: Functor[F] = f
}
}
implicit def idIsAlsoAFunctor[A]
: EverythingIsAlwaysAFunctor[A, A, Id] = {
new EverythingIsAlwaysAFunctor[A, A, Id] {
def apply(a: A): Id[A] = a
def functor: Functor[Id] = implicitly[Functor[Id]]
}
}
}
This thing does the following:
If the value A is already of shape F[B] for some functor F, then uses this functor
In all other cases, it pretends that A is actually Id[A]
Now you can write your DoSomething-pimp-my-library-syntax thing with a single doSomething method:
implicit class DoSomething[A, F[_]](a: A)(
implicit eiaaf: EverythingIsAlwaysAFunctor[A, Int, F]
) {
def doSomething: F[String] = eiaaf.functor.map(eiaaf(a))("*" * _)
}
and then it just works in all cases:
val x = Option(42).doSomething
val y = 42.doSomething
println(x)
println(y)
prints:
Some(******************************************)
******************************************
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)
I'm playing with monad transformers in scalaz. I'm trying to stack together a Writer on the top of Reader with the underlying Id monad. For combining them I'm using MonadReader and MonadWriter type classes.
I managed to compile and run the following code sample without the writer (i.e. with the Reader monad, i.e. ReaderT[Id.Id, String, A]). When adding a WriterT to the stack, I get the compilation error:
Gist.scala:10: could not find implicit value for parameter F: scalaz.MonadReader[Gist.R,String]
val MR = MonadReader[R, String]
^
How can I obtain an instance of MonadReader for my transformer stack? Do I have to make use of ReaderWriterStateT or is there another way?
Full code:
import scalaz.{Id, MonadListen, MonadReader, ReaderT, WriterT}
object Gist {
import scalaz.std.list._
import scalaz.syntax.monad._
type P[A] = ReaderT[Id.Id, String, A]
type R[A] = WriterT[P, List[String], A]
val MR = MonadReader[R, String]
val MW = MonadListen[R, List[String]]
def apply: R[String] = MR.ask >>= { greeting =>
MW.tell(List(s"greeting $greeting")) >>= { _ =>
MW.point(s"Hello $greeting")
}
}
}
I'm not entirely sure why Scalaz doesn't provide this instance (or MonadReader instances for similar monad transformers), but I'd guess the answer has something to do with the fact that WriterTInstanceN already goes past 11 and adding in MonadReader would just make things even more of a mess.
You could dig around in Scalaz's GitHub issues (or even ask on the IRC channel if you have the stomach for that kind of thing), but I'm not sure the answer matters all that much.
You can pretty straightforwardly port the instance from Haskell's mtl:
instance (Monoid w, MonadReader r m) => MonadReader r (Strict.WriterT w m) where
ask = lift ask
local = Strict.mapWriterT . local
reader = lift . reader
Which translated into Scala looks like this:
import scalaz.{ MonadReader, MonadTrans, Monoid, WriterT }
import scalaz.syntax.monad._
implicit def monadReaderForWriterT[F[_], I, W](implicit
F: MonadReader[F, I],
W: Monoid[W]
): MonadReader[WriterT[F, W, ?], I] = new MonadReader[WriterT[F, W, ?], I] {
def ask: WriterT[F, W, I] = MonadTrans[WriterT[?[_], W, ?]].liftM(F.ask)
def local[A](f: I => I)(fa: WriterT[F, W, A]): WriterT[F, W, A] =
fa.mapT(F.local(f))
def point[A](a: => A): WriterT[F, W, A] = a.point[WriterT[F, W, ?]]
def bind[A, B](fa: WriterT[F, W, A])(
f: A => WriterT[F, W, B]
): WriterT[F, W, B] = fa.flatMap(f)
}
Note that I'm using kind-projector, since the type lambda version would be more like four or five times as long as the Haskell version instead of just three times.
Once you've defined this instance, you can write the following:
import scalaz.{ Id, MonadListen, ReaderT }
import scalaz.std.list._
type P[A] = ReaderT[Id.Id, String, A]
type R[A] = WriterT[P, List[String], A]
val MR = MonadReader[R, String]
val MW = MonadListen[R, List[String]]
def apply: R[String] = MR.ask >>= { greeting =>
MW.tell(List(s"greeting $greeting")) >>= { _ =>
MW.point(s"Hello $greeting")
}
}
I am trying to create an implicit converter that would would use a implicit converter that's currently in scope (eg. A => B) and would be able to convert any type of Traversable[A] to Traversable[B].
So far I got:
implicit def convertLists[A, B](from: Traversable[A])(implicit conv: A => B): Traversable[B] = from.map(conv)
This however does not work with:
val listOfB: List[B] = convertLists(List[A]())
If I change Traversable to List, then it works fine, eg:
implicit def convertLists[A, B](from: List[A])(implicit conv: A => B): List[B] = from.map(conv)
Do I need to add anything else to allow the converter to accept any subclass of Traversable?
You have explicitly defined convertLists to return Traversable[B]. Traversable is not a subtype of List (it's its supertype), so the result of convertLists (Traversable) can't be a return type of listOfB (List).
You can define convertLists to infer the result type based on the type of its argument, if you use CanBuildFrom:
import scala.collection.TraversableLike
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds
// `CC` is some concrete subtype of `Traversable`
// `That` is an automatically inferred result collection type
implicit def convertLists[A, B, CC[T] <: TraversableLike[T, CC[T]], That](
from: CC[A]
)(
implicit
conv: A => B,
// witness that it's possible to build
// a collection with elements `B` from a collection `CC[A]`,
// and compute the resulting collection type `That`
bf: CanBuildFrom[CC[A], B, That]
): That = from.map(conv)
Now assuming the following simple definition of A and B
case class A(i: Int)
case class B(i: Int)
implicit def aisb(a: A): B = B(a.i)
The following works:
val listOfB: List[B] = convertLists(List[A](A(1)))
And you don't have to call convertLists explicitly:
val listOfB2: List[B] = List[A](A(1))
Using the approach in scala collections library you could come out with such code:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
implicit val boolToInt = (b: Boolean) => if (b) 1 else 0
implicit def convertLists[A, B, Repr, That](from: TraversableLike[A, Repr])(implicit conv: A => B, bf: CanBuildFrom[Repr, B, That]): That = from map conv
val listOfB: List[Int] = List(true, false)
which gives
listOfB: List[Int] = List(1, 0)