Suppose that I have the following scala code:
trait ValueSource[A] {
def value(a: Int): A
}
trait ValueSourceOps[A] {
def self: Int
def F: ValueSource[A]
def value: A = F.value(self)
}
trait ToValueSourceOps {
implicit def toValueSourceOps[A](index: Int)(implicit F0: ValueSource[A]): ValueSourceOps[A] = new ValueSourceOps[A] {
def self = index
def F: ValueSource[A] = F0
}
}
object Test extends ToValueSourceOps {
def value[A: ValueSource](index: Int): A = toValueSourceOps(index).value
}
The code above compiles well, but when I change the last line (body of method "value" in object Test) to
def value[A: ValueSource](index: Int): A = index.value
the compiler complains that
could not find implicit value for parameter F0: ValueSource[A]
In my opinion, def value[A: ValueSource] means I have a implicit value "ValueSource[A]", then why does the compilation fail?
The A in toValueSourceOps has no relationship with the A in value, which makes inferring it problematic. To me the real question is why it works when you call the method explicitly.
I'm guessing that, when toValueSourceOp is called explicitly, it has to infer the same A because that's the only implicit available.
Related
I have written this code
trait Input[F[_]] {
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for {
_ <- write("What is your name")
name <- read
} yield name
}
This code doesn't compile obviously because the compiler has no way of knowing that the type F supports flatmap. So I change my code to
import scalaz._
import Scalaz._
trait Input[F[_] : Monad] {
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for {
_ <- write("What is your name")
name <- read
} yield name
}
but now I get compile time error traits cannot have type parameters with context bounds.
So how can I specify constraints on my type parameter so that it always supports flatmap?
trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:
def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad] {}
Will work because it is translated to:
def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F]) {}
I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.
For your case, if you really need to inside a trait to constraint F to a Monad for example, then:
trait Input[F[_]] {
val M: Monad[F]
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)
}
I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:
object Main extends App{
class IOInput extends Input[IO] {
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))
}
val impl = new IOInput
println(impl.getName.unsafeRunSync())
}
P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.
This works
trait SomeTrait {
type T
def write2( s: String): T
}
case class C() extends SomeTrait {
type T = String
override def write2(s:String): T = s }
But this does not
trait SomeTrait {
def write2[T]( s: String): T
}
case class C() extends SomeTrait {
override def write2(s: String): String =s }
To my reasoning, they ..seem similar. Why specifically does the compiler give a "method does not override anything" error? IS there a way of making this work?
If you use this definition:
trait T {
def write2[T]( s: String): T
}
Consider some client using this trait. For example:
def doSomething(t: T): Unit = {
val s: String = t.write2[String]("hello")
val n: Int = t.write2[Int]("world")
val d: Double = t.write2[Double]("!")
println(s + n.toString + d.toString)
}
I don't know what the values of s, n, and d would be, but in theory that would be a perfectly valid usage of the trait, from the compiler's perspective. So in order to truly override that write2[T] method, you would have to provide valid behavior for all possible types T.
Compare that to:
trait T2 {
type T
def write2( s: String): T
}
Or even:
trait T3[T] {
def write2(s: String): T
}
Then when callers use it:
def doSomething(t: T2): Unit = {
val x = t.write2("hello") // always returns type t.T
}
def doSomething[T](t: T3[T]): Unit = {
val x = t.write2("hello") // always returns type T
}
There's only one possible type that can be returned, once you have a specific instance of that trait. So to override that method, you need only override the behavior for that one type.
Your trait definition in the second snippet does not mean that implementations of it must have a method write2 for some type T, but that it must have a method write2 which takes a type parameter T.
That means that, if you have a value v: SomeTrait, you should be able to do
val stringed: String = v.method2[String]("foo")
val inted: Int = v.method2[Int]("foo")
This compiles:
trait T {
def write2[T]( s: String): T
}
case class C() extends T {
override def write2[T](s: String): T =s.asInstanceOf[T]
}
write2 returns a T, not a String (hence the reason why your second override does not work and the necessity in the code above for the ugly cast)
I have the following code and I wonder if the nasty thing could be removed. Override doesn't work if I add implicit parameter.
class FromEnumFormat[T <: Enum[T]] extends JsonFormat[T] {
override def read(json: JsValue): T = readit(json)
def readit(json: JsValue)(implicit m: Manifest[T]): T = {
val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]
json match {
case s: JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass, s.value.toUpperCase()).asInstanceOf[T]
case unknown => deserializationError(s"unknown Status: $unknown")
}
}
override def write(obj: T): JsValue = JsString(obj.name().toLowerCase)
}
Is there a way how to get rid of this line
override def read(json: JsValue): T = readit(json)
The question is essentially: Are the implicit parameters part of method signature?
UPDATE:
Code doesn't compile. So correct solution should be:
class FromEnumFormat[T<: Enum[T]] extends JsonFormat[T] {
implicit val m: Manifest[T] = ???
override def read(json: JsValue): T = {
val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]
json match {
case s :JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass ,s.value.toUpperCase()).asInstanceOf[T]
case unknown => deserializationError(s"unknown Status: ${unknown}")
}
}
override def write(obj: T): JsValue = {JsString(obj.name().toLowerCase)}
}
The question is how to access Manifest? I am using Scala 2.10
UPDATE:
Find that the issue is with scala reflection not with implicits and overrides, hence closing this question.
To answer your question, yest, implicit parameters are part of method signature. However, as it is implicit, this means you can call the def readit(json: JsValue)(implicit m: Manifest[T]): T function without mentioning it, as long as it has been declared somewhere in the code :
implicit val manifest = /* whatever a Manifest is*/
readit(jsonValue)
Could you please provide an example of what you'd like to do ?
Your final solution is nearly correct, but it has m in the wrong place, it should be a class parameter instead:
class FromEnumFormat[T<: Enum[T]](implicit m: Manifest[T]) extends JsonFormat[T] {
override def read(json: JsValue): T = {
val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]
json match {
case s :JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass ,s.value.toUpperCase()).asInstanceOf[T]
case unknown => deserializationError(s"unknown Status: ${unknown}")
}
}
override def write(obj: T): JsValue = {JsString(obj.name().toLowerCase)}
}
This way the compiler can insert it when creating a FromEnumFormat with a specific enum:
val format = new FromEnumFormat[TimeUnit]
If you want to create a generic FromEnumFormat[T], though, you'll have to pass implicit m: Manifest[T] as an argument:
def doSomethingWithFormat[T <: Enum[T]](implicit m: Manifest[T]) = {
val format = new FromEnumFormat[T]
...
}
Implicit parameters are not exactly part of the signature. But So you cannot add an implicit parameter by means of overloading.
Here's why. Multiple parameter list syntax is just a syntactic sugar. The code
def readit(json: JsValue)(implicit m: Manifest[T]): T = ???
gets desugared to
def readit(json: JsValue): Function1[Manifest[T], T] = {
def inner(implicit m: Manifest[T]): T = ???
inner
}
So as you see the real type of readit just doesn't match the type of read, thus it is not a proper override.
UPD.
As Alexey pointed out formally multiple parameter list contributes to type signature (see section 4.6 Function Declarations and Definitions of scala spec).
A function declaration has the form def fpsig: T, where f is the function's name, psig is its parameter signature and T is its result type.
A parameter signature consists of an optional type parameter clause
[tps], followed by zero or more value parameter clauses
(ps1)…(psn).
How can i solve this simple problem. Class Conversion has a typed method from wich takes two type parameters A and B and returns a B from an A. I have defined some implicits in the companion object to provide default beahviour.
My Problem is when i try to forward the call to the Conversion class within another typed method which has the same signature it does not work. Here in my example i try to forward the call from function myFun to my Conversion class.
I got following error
not enough arguments for method from: (implicit f: A => B)
I am wondering why this makes any problems. Can someone explain me why and how to overcome this problem ?
Here is the code
object MyConversions {
implicit val IntToStr = (f:Int) => f.toString()
implicit val DoubleToStr = (f:Double) => f.toString()
implicit val BooleanToStr = (f:Boolean) => f.toString()
}
class Conversions{
def from[A,B](a:A)(implicit f:(A) => B) = {
f(a)
}
}
import MyConversions._;
def myFun[A,B](a:A){
// Error
new Conversions().from[A, B](a)
}
// Working
println( new Conversions().from[Int, String](3) )
The problem is that the Scala compiler cannot find an implicit value for the parameter f: (A) => B in the scope of myFun. What you have to do is to tell the compiler that myFun can only be called, when there is such a value available.
The following code should do the trick
object App {
trait Convertible[A, B] {
def convert(a: A): B
}
object Convertible {
implicit val int2String = new Convertible[Int, String] {
override def convert(a: Int): String = a.toString
}
implicit val float2String = new Convertible[Float, String] {
override def convert(a: Float): String = a.toString
}
}
def myFun[A ,B](a:A)(implicit converter: Convertible[A, B]): B = {
converter.convert(a)
}
def main(args: Array[String]): Unit = {
println(myFun(3))
}
}
Lets say we want to use type classes to implement pretty printing:
trait Printer[T] {def print(t: T)}
with default implementation for ints:
implicit object IntPrinter extends Printer[Int] {
override def print(i : Int): Unit = println(i)
}
Our specific types we want to print are:
trait Foo {
type K
val k: K
}
class IntFoo extends Foo {
override type K = Int
override val k = 123
}
cool. Now I want to build printers for all Foos with printable Ks
implicit def fooPrinter[FP <: Foo](implicit ev: Printer[FP#K]): Printer[FP] =
new Printer[FP] {
override def print(f: FP): Unit = {
Predef.print("Foo: ")
ev.print(f.k)
}
}
lets check that implicits are resolved:
def main(args: Array[String]) {
implicitly[Printer[Int]]
implicitly[Printer[IntFoo]]
}
scalac 2.11.2 says:
diverging implicit expansion for type Sandbox.Printer[Int]
starting with method fooPrinter in object Sandbox
implicitly[Printer[Int]]
whaat?
OK, lets rewrite fooPrinter:
implicit def fooPrinter[KP, FP <: Foo {type K = KP}](implicit ev: Printer[KP]) =
new Printer[FP] {
override def print(f: FP): Unit = {
Predef.print("Foo: ")
ev.print(f.k)
}
}
this works in 2.11, but what's the problem with the first approach?
Unfortunately we're on 2.10, and second solution still doesn't work. It compiles until we add one more sime printer like
implicit object StringPrinter extends Printer[String] {
override def print(s : String): Unit = println(s)
}
and it mysteriously breaks Printer[IntFoo] implicit:
could not find implicit value for parameter e:
Sandbox.Printer[Sandbox.IntFoo]
compiler bugs?
Order of implicit declarations matters. In your source code reorder original code from
implicit object IntPrinter ...
...
implicit def fooPrinter ...
to
implicit def fooPrinter ...
...
implicit object IntPrinter ...