Stacking implicits conversions - scala

I'm trying to make my use of futures as lightweight as possible.
Here is my current test code :
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
object Test1 extends App {
def lift[A](a: A): Future[A] = Future { a }
def ap[A, B](fct: Future[A => B], param: Future[A]): Future[B] =
for {
c <- param
o <- fct
} yield (o(c))
implicit def valToFuture[A](elem: A): Future[A] = lift(elem)
implicit class FutureInfix[A, B](val x: Future[A => B]) extends AnyVal {
def <*>(that: Future[A]) = ap(this.x, that)
}
val plus1: Int => Int = (x: Int) => x + 1
val cst1: Int = 1
val extracted: Future[Int] = ap(plus1, cst1)
val extracted2: Future[Int] = lift(plus1) <*> lift(cst1)
val extracted3: Future[Int] = plus1 <*> cst
/*
* - value <*> is not a member of Int ⇒ Int
* - not found: value cst
*/
}
extracted and extracted2 are working but are each using only one of the two implicit conversion I've defined.
extracted3 is what I am aiming at, implicitly lifting plus and cst1 to Future[X] values and converting a <*> b to ap(a,b). But the compiler does not seems to agree with me.
Is what i'm trying to achieve possible ? If so, what do I have to change to make it works ?
PS : This i kind of inspired from what I've seen using haskell.

I think you're bumping up against the "one at a time" rule.
From Programming in Scala, (1st edition):
One-at-a-time Rule: Only one implicit is tried. The compiler will
never rewrite x + y to convert1(convert2(x)) + y. Doing so would cause
compile times to increase dramatically on erroneous code, and it would
increase the difference between what the programmer writes and what
the program actually does. For sanity's sake, the compiler does not
insert further implicit conversions when it is already in the middle
of trying another implicit.
As #tkachuko has pointed out, there likely is a work-around for this limitation using implicit parameters, but one simple solution is to split FutureInfix into two parts.
implicit class FromFutureInfix[A, B](x: Future[A => B]) {
def <*>(that: Future[A]) = ap(x, that)
}
implicit class ToFutureInfix[A, B](x: A => B) {
def <*>(that: A) = ap(x, that)
}

Related

What's the point of implicit conversions as parameters?

I'm reading the docs on implicits in Scala, and there is an example of a function with implicit conversion as parameter:
def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
I understand how it works, but I don't understand what's the point of writing it like that instead of:
def getIndexExplicit[T](seq: Seq[T], value: T) = seq.indexOf(value)
As far as I know, if the conversion from the argument seq to type Seq[T] exists, the compiler would still allow the call to getIndexExplicit?
To illustrate my point, I prepared this simple example:
def equal42[T](a: T)(implicit conv: T => Int) = conv(a) == 42 // implicit parameter version
def equal42Explicit(a: Int) = a == 42 // just use the type in the signature
implicit def strToInt(str: String): Int = java.lang.Integer.parseInt(str) // define the implicit conversion from String to Int
And indeed, both functions seem to work in the same way:
scala> equal42("42")
res12: Boolean = true
scala> equal42Explicit("42")
res13: Boolean = true
If there is no difference, what's the point of explicitly defining the implicit conversion?
My guess is that in this simple case it makes no difference, but there must be some more complex scenarios where it does. What are those?
In your super-simple example:
equal42("42")
equal42Explicit("42")
is equal to
equal42("42")(strToInt)
equal42Explicit(strToInt("42"))
which in case of your definition make no difference.
BUT if it did something else e.g.
def parseCombined[S, T](s1: S, s2: S)
(combine: (S, S) => S)
(implicit parse: S => Option[T]): Option[T] =
parse(combine(s1, s2))
then when you would apply conversion matters:
implicit def lift[T]: T => Option[T] = t => Option(t)
implicit val parseInt: String => Option[Int] = s => scala.util.Try(s.toInt).toOption
implicit def parseToString[T]: T => Option[String] = t => Option(t.toString)
parseCombined[Option[Int], String]("1", "2") { (a, b) => a.zip(b).map { case (x, y) => x + y } } // Some("Some(3)")
parseCombined[String, Int]("1", "2") { _ + _ } // Some(12)
In the first case arguments were converted before passing (and then again inside), while in the other case they were converted only inside a function at a specific place.
While this case is somewhat stretched, it shows that having control over when conversion is made might matter to the final result.
That being said such usage of implicit conversions is an antipattern and type classes would work much better for it. Actually extension methods are the only non-controversial usages of implicit conversions because even magnet pattern - the only other use case that might be used on production (see Akka) - might be seen as issue.
So treat this example from docs as a demonstration of a mechanism and not as a example of good practice that should be used on production.

Scala - restrict generic type to anything other than Future

I have a couple of methods on a trait as so:
trait ResourceFactory[+R] {
def using[T](work: R => T): T
def usingAsync[T](work: R => Future[T]): Future[T]
}
Unfortunately there's nothing in the type checker to stop you calling the first using method with a function returning a Future. I'd like the compiler to insist that the type of T in the first method be anything other than Future, to prevent that mistake - is that possible?
Thanks
You can use shapeless' <:!<:
import scala.concurrent.Future
import shapeless._
trait ResourceFactory[+R] {
def using[T](work: R => T)(implicit ev: T <:!< Future[_]): T = ???
def usingAsync[T](work: R => Future[T]): Future[T] = ???
}
Then:
scala> val r = new ResourceFactory[Int] {}
r: ResourceFactory[Int] = $anon$1#effe6ad
// Compiles (the error is due to the use of ???)
scala> r.using(_.toString)
scala.NotImplementedError: an implementation is missing
// Doesn't compile
scala> r.using(Future.successful(_))
<console>:17: error: ambiguous implicit values:
both method nsubAmbig1 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
and method nsubAmbig2 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
match expected type shapeless.<:!<[scala.concurrent.Future[Int],scala.concurrent.Future[_]]
r.using(Future.successful(_))
Here's an alternative I've stolen shamelessly from https://github.com/japgolly/scalajs-react/blob/cb75721e3bbd0033ad63d380bcaddc96fbe906e3/core/src/main/scala/japgolly/scalajs/react/Callback.scala#L21-L31:
#implicitNotFound("You're returning a ${A}, which is asynchronous, which means the resource may be closed before you try and use it. Instead use usingAsync.")
final class NotFuture[A] private[ResourceFactoryTests]()
object NotFuture {
final class Proof[A] private[ResourceFactory]()
object Proof {
implicit def preventFuture1[A]: Proof[Future[A]] = ???
implicit def preventFuture2[A]: Proof[Future[A]] = ???
#inline implicit def allowAnythingElse[A]: Proof[A] = null
}
#inline implicit def apply[A: Proof]: NotFuture[A] = null
}
which can be used as:
trait ResourceFactory[+R] {
def using[T: ResourceGuard](work: R => T): T
def usingAsync[T](work: R => Future[T]): Future[T]
}
This has the advantage of not having to add the implicit arg every time you implement the method, but the disadvantage that I'm pure cargo culting - I don't understand why it works, though it seems to use similar principles to shapeless.

How does HList.foldRight look for implicits when used in the implementation of a type class?

I am newbie at using Shapeless, and I am experimenting with Shapeless for automatic type class generation and folding over HLists.
My goal is to render a HList as (a, b, c, d) using a typeclass implementation of scalaz.Show
My first step was to experiment in the REPL with the following code
import shapeless._
import shapeless.ops.hlist._
object prettyPrint extends Poly2 {
implicit def defaultCase[A] = at((a:A, z:String)=>s", ${a.toString}$z")
}
def print[H, T<:HList](f: H :: T)(implicit folder:RightFolder.Aux[H :: T, String, prettyPrint.type, String]) = {
f.foldRight("")(prettyPrint)
}
val f = 1::'a::2::'b::HNil
val res = s"(${f.head}${print(f.tail)})" // Results res: String = (1, 'a, 2, 'b)
After this I implemented the following method in my implementation of LabelledTypeClassCompanion[...]. Unfortunately, this code does not compile because the compiler is complaining about missing implicits, even though I can't tell what the difference is between the code in the REPL and the code below. My Question is what is the problem in the code below and how can I fix it?
def showFold[H, T<:HList](f: H::T)(implicit folder:RightFolder.Aux[ H::T, String, prettyPrint.type, String]) = {
f.foldRight("")(prettyPrint)
}
override def product[H, T <: HList](name: String, ch: ScalazShow[H], ct: ScalazShow[T]): ScalazShow[H :: T] = {
new ScalazShow[H :: T] {
override def shows(ft: (H :: T)): String = {
showFold(ft) // This does not compile
}
}
}
Error:(49, 18) could not find implicit value for parameter folder: shapeless.ops.hlist.RightFolder.Aux[shapeless.::[H,T],String,com.fpinscala.ninetynine.prettyPrint.type,String]
showFold(ft) // This does not compile
Below is the complete implementation
package com.fpinscala.ninetynine
import shapeless._
import shapeless.ops.hlist.RightFolder
import scalaz.{Show => ScalazShow}
object prettyPrint extends Poly2 {
implicit def defaultCase[A]:this.Case.Aux[A, String, String] = at[A, String]{
(a,z) => s", $a$z"
}
}
object ShowImpl extends LabelledTypeClassCompanion[ScalazShow] {
implicit def symbolShow : ScalazShow[Symbol] = new ScalazShow[Symbol] {
override def shows(f: Symbol): String = f.toString()
}
implicit def intShow : ScalazShow[Int] = new ScalazShow[Int] {
override def shows(f: Int): String = f.toString
}
override val typeClass: LabelledTypeClass[ScalazShow] = new LabelledTypeClass[ScalazShow] {
override def coproduct[L, R <: Coproduct](name: String, cl: => ScalazShow[L], cr: => ScalazShow[R]): ScalazShow[L :+: R] = new ScalazShow[L :+: R] {
override def shows(lr: (L :+: R)): String = lr match {
case Inl(l) => cl.shows(l)
case Inr(r) => cr.shows(r)
}
}
override def emptyCoproduct: ScalazShow[CNil] = new ScalazShow[CNil] {
override def shows(f: CNil): String = ""
}
def showFold[H, T<:HList](f: H::T)(implicit folder:RightFolder.Aux[ H::T, String, prettyPrint.type, String]) = {
f.foldRight("")(prettyPrint)
}
override def product[H, T <: HList](name: String, ch: ScalazShow[H], ct: ScalazShow[T]): ScalazShow[H :: T] = {
new ScalazShow[H :: T] {
override def shows(ft: (H :: T)): String = {
showFold(ft) // This does not compile
}
}
}
override def project[F, G](instance: => ScalazShow[G], to: (F) => G, from: (G) => F): ScalazShow[F] = new ScalazShow[F] {
override def shows(f: F): String = instance.shows(to(f))
}
override def emptyProduct: ScalazShow[HNil] = new ScalazShow[HNil] {
override def shows(f: HNil): String = ""
}
}
}
You can think of a type class constraint as a way to carry some information about a type from a concrete context to a generic context (moving backward through the call stack). In this case you actually really do need that RightFolder instance if you want to write your implementation this way, but the method signatures in LabelledTypeClass don't allow you to carry that information through, so you're out of luck (the basic idea is possible, though—you just need a slightly different approach).
Update
I just realized I misread your question slightly—because you were using the TypeClass type class I assumed you wanted instances for case classes and sealed trait hierarchies as well as hlists and coproducts. My answer gives you all of these (just like TypeClass would), so you can write this:
scala> (123 :: "abc" :: HNil).shows
res2: String = (123, abc)
As well as the case class and sealed trait examples I give below. If you don't want case classes and sealed traits you can just remove the genericShow definition.
Why the difference between concrete and generic contexts
Here's a simpler case to start with. Suppose we want to use Show to print a value twice. We can do something like this:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> val x: Int = 123
x: Int = 123
scala> s"${ x.shows }${ x.shows }"
res0: String = 123123
Here x has a concrete type, and when we call .shows on it, the compiler will try to find an instance of Show for that concrete type. Scalaz provides a Show[Int], so everything works just fine and we get the result we want.
Next we can try writing a generic version:
def toStringTwice[X](x: X): String = s"${ x.shows }${ x.shows }"
But the compiler will complain:
<console>:18: error: value shows is not a member of type parameter X
def toStringTwice[X](x: X): String = s"${ x.shows }${ x.shows }"
^
This is because the compiler can't prove that X has a Show instance, since it doesn't know anything at all about X. You could just write a bunch of overloaded concrete methods:
scala> def toStringTwice(x: String): String = s"${ x.shows }${ x.shows }"
toStringTwice: (x: String)String
scala> def toStringTwice(x: Int): String = s"${ x.shows }${ x.shows }"
toStringTwice: (x: Int)String
...
But this is exactly the kind of annoying boilerplate that type classes are designed to save you from. Instead of enumerating all the types you have Show instances for, you can abstract over them by providing the compiler with exactly as much information as it needs:
scala> def toStringTwice[X: Show](x: X): String = s"${ x.shows }${ x.shows }"
toStringTwice: [X](x: X)(implicit evidence$1: scalaz.Show[X])String
Now you can call it with an Int, or anything else that has a Show instance:
scala> toStringTwice(123)
res2: String = 123123
What you can't do is call it with another unconstrained generic type:
def toStringFourTimes[X](x: X): String = s"${ toStringTwice(x) * 2 }"
Instead you have to add the constraint again:
scala> def toStringFourTimes[X: Show](x: X): String = s"${ toStringTwice(x) * 2 }"
toStringFourTimes: [X](x: X)(implicit evidence$1: scalaz.Show[X])String
And so on—you have to carry along the Show constraint all the way until you've got a concrete type. You can only use toStringTwice in two ways: on a concrete type that has a Show instance, or on a generic type that has a Show constraint.
Note that none of the above is Shapeless-specific—this is simply the way type classes work.
One possible fix
Unfortunately this doesn't seem to me like a very good use case for LabelledTypeClass, since the desired instance doesn't really fit the way of building up instances that the TypeClass type classes support. You could probably do it but I don't really want to try.
There's also an issue in the way your prettyPrint works—it's not actually using the Show instance for A (there's not even one to use), but is instead calling the horrible universal toString.
Here's a quick first draft of how I'd probably write this:
import scalaz.Show, scalaz.Scalaz._
import shapeless._
import shapeless.ops.coproduct.Folder
import shapeless.ops.hlist.RightReducer
object prettyPrint2 extends Poly2 {
implicit def defaultCase[A: Show]: Case.Aux[A, String, String] =
at[A, String]((a, z) => s"$a, $z")
}
object prettyPrint extends Poly1 {
implicit def defaultCase[A: Show]: Case.Aux[A, String] = at[A](_.shows)
}
implicit def hlistShow[L <: HList](implicit
reducer: RightReducer.Aux[L, prettyPrint2.type, String]
): Show[L] = Show.shows(l => "(" + l.reduceRight(prettyPrint2) + ")")
implicit def coproductShow[C <: Coproduct](implicit
folder: Folder.Aux[prettyPrint.type, C, String]
): Show[C] = Show.shows(_.fold(prettyPrint))
implicit def genericShow[A, R](implicit
gen: Generic.Aux[A, R],
reprShow: Show[R]
): Show[A] = reprShow.contramap(gen.to)
And then:
scala> Foo(123, "abc").shows
res0: String = (123, abc)
scala> (Foo(123, "abc"): Base).shows
res1: String = (123, abc)
You may run into corner cases involving nested case classes, etc. that don't work because of compiler bugs (see my slides here about generic derivation in Scala for some details), but this approach should more or less do what you want.

Scala: bug in implicit parameter

The following is a simplified version of my real problem:
class Z[T]
object E extends Enumeration {
implicit val z = new Z[Value]
val X, Y = Value
}
implicit def f[T : Z] = (getter: T) => 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
def e: Option[E.Value] = null
val b: Int = e
This works, with b implicitly converted to o(e)(f(E.z)). But with the small changes following:
implicit def f[T : Z] = (setter: T => Unit) => 0
implicit def o[T](v: Option[T])(implicit toInt: (T => Unit) => Int) = 0
it fails finding the appropriate implicit value E.z although there's no essential difference from the original code, while manual explicit conversion to o(e)(f(E.z)) still works.
I know the implementation of implicit parameter is not complete yet and there are still many unresolved issues. If this is one of them, I'd like to report it to the Scala contributors. So my question is, a) is this really a bug? b) if so, where and how can I file a bug so that it could be fixed in the future?
UPDATE
Travis' answer worked like a charm! By the way, the code above was a workaround to my original problem:
implicit object E extends Enumeration { val X, Y = Value }
implicit object F extends Enumeration { val X, Y = Value }
implicit def f[T <: Enumeration](getter: T#Value)(implicit e: T) = 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
val b: Int = Some[E.Value](null)
In this code, the situation was the other way around: it works with the setter version but not with the simpler getter version. The compiler complains that it's confusing whether to use E or F as the implicit parameter though using F doesn't actually compile nor make sense. I managed to get it working by doing a similar thing:
implicit def f[S <% T => T, T <: Enumeration](getter: T#Value)(implicit e: T) = 0
This works, and although I somehow could get it working, I still don't understand the logic behind this magic.
You've run into a yet another variation of this limitation of Scala's type inference system.
The compiler will resolve the T for f if in the first case, where it's looking for an implicit conversion from plain old E.Value to Int, but not in the second, where it wants a conversion from E.Value => Unit (i.e., Function1[E.Value, Unit]) to Int.
Fortunately there's an easy workaround in cases like this—just use a view bound:
implicit def f[F <% T => Unit, T: Z] = (setter: F) => 0
This will desugar to something like the following:
implicit def f[F, T](implicit st: F <:< (T => Unit), ev: Z[T]) = (setter: F) => 0
Now when the compiler wants a conversion from E.Value => Unit to Int it'll be able to resolve F to E.Value => Unit immediately and then T to E.Value.

Reader Monad with Scalaz

I try to define the Reader monad with scalaz like this:
import scalaz._
import Scalaz._
final class Reader[E,A](private[Reader] val runReader: E => A)
object Reader {
def apply[E,A](f: E => A) = new Reader[E,A](f)
def env[E]: Reader[E,E] = Reader(identity _)
implicit def ReaderMonad[E] = new Monad[PartialApply1Of2[Reader,E]#Apply] {
def pure[A](a: => A) = Reader(_ => a)
def bind[A,B](m: Reader[E,A], k: A => Reader[E,B]) =
Reader(e => k(m.runReader(e)).runReader(e))
}
}
object Test {
import Reader._
class Env(val s: String)
def post(s: String): Reader[Env, Option[String]] =
env >>= (e => if (e.s == s) some(s).pure else none.pure)
}
but I get a compiler error:
reader.scala:27: reassignment to val
env >>= (e => if (e.s == s) some(s).pure else none.pure)
^
Why is that?
Thanks,
Levi
This error is fairly opaque, even by Scala's standards. Method names ending with = are treated specially -- they are first considered as a normal identifier, and failing that, they are expanded to a self assignment.
scala> def env[A] = 0
env: [A]Int
scala> env >>= 0
<console>:7: error: reassignment to val
env >>= 0
^
scala> env = env >> 0
<console>:6: error: reassignment to val
env = env >> 0
^
If you're confused about the syntactic interpretation of your program, it's a good idea to run scalac -Xprint:parser to see what's going on. Similarly, you can use -Xprint:typer or -Xprint:jvm to see later phases of the program transformation.
So, how do you call >>= on your Reader? First of all, you'll need to explicitly pass the type argument Env to env. The resulting Reader[Env, Env] must then be converted to a MA[M[_], A]. For simple type constructors, the implicit conversion MAs#ma will suffice. However the two param type constructor Reader must be partially applied -- this means it can't be inferred and instead you must provide a specific implicit conversion.
The situation would be vastly improved if Adriaan ever finds a spare afternoon to implement higher-order unification for type constructor inference. :)
Until then, here's your code. A few more comments are inline.
import scalaz._
import Scalaz._
final class Reader[E, A](private[Reader] val runReader: E => A)
object Reader {
def apply[E, A](f: E => A) = new Reader[E, A](f)
def env[E]: Reader[E, E] = Reader(identity _)
implicit def ReaderMonad[E]: Monad[PartialApply1Of2[Reader, E]#Apply] = new Monad[PartialApply1Of2[Reader, E]#Apply] {
def pure[A](a: => A) = Reader(_ => a)
def bind[A, B](m: Reader[E, A], k: A => Reader[E, B]) =
Reader(e => k(m.runReader(e)).runReader(e))
}
// No Higher Order Unification in Scala, so we need partially applied type constructors cannot be inferred.
// That's the main reason for defining function in Scalaz on MA, we can create one implicit conversion
// to extract the partially applied type constructor in the type parameter `M` of `MA[M[_], A]`.
//
// I'm in the habit of explicitly annotating the return types of implicit defs, it's not strictly necessary
// but there are a few corner cases it pays to avoid.
implicit def ReaderMA[E, A](r: Reader[E, A]): MA[PartialApply1Of2[Reader, E]#Apply, A] = ma[PartialApply1Of2[Reader, E]#Apply, A](r)
}
object Test {
import Reader._
class Env(val s: String)
def post(s: String): Reader[Env, Option[String]] =
// Need to pass the type arg `Env` explicitly here.
env[Env] >>= {e =>
// Intermediate value and type annotation not needed, just here for clarity.
val o: Option[String] = (e.s === s).guard[Option](s)
// Again, the partially applied type constructor can't be inferred, so we have to explicitly pass it.
o.pure[PartialApply1Of2[Reader, Env]#Apply]
}
}