I am trying to create a type class inside IntelliJ Scala Worksheet. So I started with trait like this
trait Show[A] {
def show(a : A) : String
}
and created a companion object
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
When I try
println(Show.show(20))
I get this error.
Error:(50, 26) could not find implicit value for parameter sh: Show[Int]
println(Show.show(20))
But when I take the intCanShow out of the object Show, it works fine. Why cannot scala acess the the implicit inside the object?
Implicit resolution tries companion objects so your code seems ok. However for an object to become a companion it must satisfy the following two requirements
A companion object is an object with the same name as a class or trait, and
is defined in the same source file as the associated class or trait.
The following warning means the second requirement is not satisfied:
defined object Show
warning: previously defined trait Show is not a companion to object Show.
Companions must be defined together; you may wish to use :paste mode for this.
To satisfy second requirement we have to use Plain evaluation model in Scala Worksheet, or :paste mode in Scala REPL.
Scala Worksheet Plain evaluation model
To define a companion object in IntelliJ Scala Worksheet change Run type to Plain like so
Show Worksheet Settings
Select tab Settings for *.sc
Change Run type from REPL to Plain
Scala REPL paste mode
As per #jwvh suggestion, make sure to enter paste mode
If a class or object has a companion, both must be defined in the same
file. To define companions in the REPL, either define them on the same
line or enter :paste mode.
as demonstrated here.
Your example appears to work as expected when run as a scala script.
With the following in a file named test.sh and marked executable
#!/usr/bin/env scala
trait Show[A] {
def show(a : A) : String
}
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
println(Show.show(20))
I observe
bash-3.2$ ./test.sh
int 20
Related
I'm trying to port parts of a Haskell library for datatype-generic programming to Scala. Here's the problem I've run into:
I've defined a trait, Generic, with some container-type parameter:
trait Generic[G[_]] {
// Some function declarations go here
}
Now I have an abstract class, Collect, with three type parameters, and a function declaration (it signifies a type than can collect all subvalues of type B into a container of type F[_] from some structure of type A):
abstract class Collect[F[_],B,A] {
def collect_ : A => F[B]
}
In order to make it extend Generic, the first two type parameters F[_] and B are given, and A is curried (this effect is simulated using type lambdas):
class CollectC[F[_],B] extends Generic[({type C[A] = Collect[F,B,A]})#C] {
// Function definitions go here
}
The problem is that I need the last class definition to be implicit, because later on in my code I will need to be able to write functions like
class GUnit[G[_]](implicit gg: Generic[G]) {
// Some definitions
}
When I simply prepend implicit to the class definition, I get the an error saying implicit classes must accept exactly one primary constructor parameter. Has anyone encountered a similar problem? Is there a known way to work around it? I don't currently see how I could refactor my code while keeping the same functionality, so any advice is welcome. Thanks in advance!
Implicit classes don't work that way. They are a shorthand for implicit conversions. For instance implicit class Foo(i: Int) is equal to class Foo(i: Int); implicit def Foo(i: Int) = new Foo(i). So it only works with classes that have exactly one parameter in their constructor. It would not make sense for most 0 parameter (type-)classes.
The title of your question also seems to suggest that you think the compilation error is talking about type parameters of the type constructor, but I hope the above paragraph also makes clear that it is actually talking about value parameters of the value constructor.
For what (I think) you are trying to do, you will have to provide an implicit instance of CollectC yourself. I suggest putting it in the companion object of Collect. But you can choose an alternative solution if that fits your needs better.
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Generic[G[_]] {
// Some function declarations go here
}
abstract class Collect[F[_],B,A] {
def collect_ : A => F[B]
}
object Collect {
implicit def mkCollectC[F[_],B]: CollectC[F,B] = new CollectC[F,B]
}
class CollectC[F[_],B] extends Generic[({type C[A] = Collect[F,B,A]})#C] {
// Function definitions go here
}
// Exiting paste mode, now interpreting.
warning: there were four feature warnings; for details, enable `:setting -feature' or `:replay -feature'
defined trait Generic
defined class Collect
defined object Collect
defined class CollectC
scala> implicitly[Generic[({type C[X] = Collect[List,Int,X]})#C]]
res0: Generic[[X]Collect[[+A]List[A],Int,X]] = CollectC#12e8fb82
Given a parameterized type:
trait Document[S]
I want to bind an instance of this for an embedded interpreter, e.g.
def test[S](doc: Document[S]) = tools.nsc.interpreter.NamedParam("document", doc)
This wants both a TypeTag and a ClassTag of Document[S]. Note that I need to be able to bind the full type, i.e. Document[S] and not just Document[_].
How would I go about this? I imagine I would add something to document, e.g.
trait Document[S] {
def tt: reflect.runtime.universe.TypeTag[Document[S]] = ???
def ct: reflect.runtime.universe.ClassTag[Document[S]] = ???
}
(why the heck do I need two different tags to get the named parameter?)
EDIT: The following makes it compile
trait Document[S] {
implicit def systemType: reflect.runtime.universe.TypeTag[S]
}
def test[S](doc: Document[S]) = {
import doc.systemType
tools.nsc.interpreter.NamedParam("document", doc)
}
But I still end up with a binding to Document[_] in the interpreter, so my type parameter to Document is lost?!
I have a type alias in my code like so:
type Time = Double
And I often in both tests and in applications pass Long values to functions that use this type. For instance:
def at(time : Time) : T = {
// Do Something
}
at(System.currentTimeMillis)
This code works fine unless run in my tests where I get the following error:
found : Long
required: com.github.oetzi.echo.Echo.Time
Note that implicit conversions are not applicable because they are ambiguous:
both method long2double in object Predef of type (x: Long)Double
and method longToDouble in trait NumericBaseMatchers of type (s: Long)Double
are possible conversion functions from Long to com.github.oetzi.echo.Echo.Time
After looking up NumericBaseMatchers it seems its part of the Specs testing framework (my tests are written in Specs 1). I tried running code to get the error in the interpreter and it was fine out side of the tests.
Is there any way I can somehow remove the ambiguity so I can pass Long to values to a Double/Time function? Why does Specs try and create its own LongToDouble conversion when Scala already provides this?
If you want to deactivate an inherited implicit conversion you can do this:
override def longToDouble(s: Long) = super.longToDouble(s)
For convenience if you add it to a new trait, you can mix-in your trait to your specification when needed:
trait NoConversion {
override def longToDouble(s: Long) = super.longToDouble(s)
}
class MySpecification extends NoConversion {
...
}
Try unimporting one of them.
import NumericBaseMatchers.{longToDouble => _}
It's often convenient to test things out in the Scala interpreter. However, one issue I run into is that I have to restructure code that uses implicit conversions because defining an object with the same name as an existing class does not make it a companion module in the REPL. As a result, I can't be confident my code will still work when I translate back to "real source".
Is there a way to define companions in the REPL? Maybe something along the lines of
bigblock {
class A
object A {
implicit def strToA(s: String): A = // ...
}
}
such that
val v: A = "apple"
will compile.
That's close:
object ABlock {
class A
object A {
implicit def strToA(s: String): A = // ...
}
}
import ABlock._
Or, the following, if you put everything on one line:
class A; object A { implicit def strToA(s: String): A = // ... } }
...though either way you'll still need to import the implicit conversion to make the following work as you requested:
import ABlock.A.strToA // for the form with the enclosing object
import A.strToA // for the one-line form without an enclosing object
val v: A = "apple"
The reason you need to do this is that every line you enter at the REPL is enclosed in an object and each subsequent one is nested within the immediately preceding one. This is done so you can do things like the following without getting redefinition errors:
val a = 5
val a = "five"
(Effectively, the second definition of a here shadows the first.)
With more recent versions use can use the :paste command.
When trying to figure how a library works, implicit conversions are confusing. For example, looking at an expression like 'val foo: Foo = 1', what converts 1 to Foo?
Is it possible to instruct the scala library (or REPL) to print out the code paths that are executing while evaluating an expression?
You can add "-Xprint:typer" to the compiler command line (or "-Ybrowse:typer" for a swing GUI browser) to see the code with the conversions explicitly applied.
As an alternative to printing out the conversions, one must realize implicits can't just come out of the blue. You have to bring them into scope in some way. The alternatives are:
Explicit import statement. Watch out for import x.y._ when y is an object, as this is the only way to bring in an implicit into scope.
The object companion of the class that is being converted into something else.
The object companion of the target class, as long as that target is made explicit somehow (such as in your example).
Note that the object scala.Predef is all imported into scope by default, which is how Scala's default implicits get into scope.
scalac -print prints the code after implicit type conversions where applied.
class A{
val x : String = "hi" drop 1
}
Will result in:
package <empty> {
class A extends java.lang.Object with ScalaObject {
#remote def $tag(): Int = scala.ScalaObject$class.$tag(A.this);
private[this] val x: java.lang.String = _;
<stable> <accessor> def x(): java.lang.String = A.this.x;
def this(): A = {
A.super.this();
A.this.x = scala.this.Predef.forceRandomAccessCharSeq(
scala.this.Predef.stringWrapper("hi").drop(1));
()
}
}
}