I am trying to learn Scala now, with a little bit of experience in Haskell. One thing that stood out as odd to me is that all function parameters in Scala must be annotated with a type - something that Haskell does not require. Why is this? To try to put it as a more concrete example: an add function is written like this:
def add(x:Double, y:Double) = x + y
But, this only works for doubles(well, ints work too because of the implicit type conversion). But what if you want to define your own type that defines its own + operator. How would you write an add function which works for any type that defines a + operator?
Haskell uses Hindley-Milner type inference algorithm whereas Scala, in order to support Object Oriented side of things, had to forgo using it for now.
In order to write an add function for all applicable types easily, you will need to use Scala 2.8.0:
Welcome to Scala version 2.8.0.r18189-b20090702020221 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import Numeric._
import Numeric._
scala> def add[A](x: A, y: A)(implicit numeric: Numeric[A]): A =
| numeric.plus(x, y)
add: [A](x: A,y: A)(implicit numeric: Numeric[A])A
scala> add(1, 2)
res0: Int = 3
scala> add(1.1, 2.2)
res1: Double = 3.3000000000000003
In order to solidify the concept of using implicit for myself, I wrote an example that does not require scala 2.8, but uses the same concept. I thought it might be helpful for some.
First, you define an generic-abstract class Addable:
scala> abstract class Addable[T]{
| def +(x: T, y: T): T
| }
defined class Addable
Now you can write the add function like this:
scala> def add[T](x: T, y: T)(implicit addy: Addable[T]): T =
| addy.+(x, y)
add: [T](T,T)(implicit Addable[T])T
This is used like a type class in Haskell. Then to realize this generic class for a specific type, you would write(examples here for Int, Double and String):
scala> implicit object IntAddable extends Addable[Int]{
| def +(x: Int, y: Int): Int = x + y
| }
defined module IntAddable
scala> implicit object DoubleAddable extends Addable[Double]{
| def +(x: Double, y: Double): Double = x + y
| }
defined module DoubleAddable
scala> implicit object StringAddable extends Addable[String]{
| def +(x: String, y: String): String = x concat y
| }
defined module StringAddable
At this point you can call the add function with all three types:
scala> add(1,2)
res0: Int = 3
scala> add(1.0, 2.0)
res1: Double = 3.0
scala> add("abc", "def")
res2: java.lang.String = abcdef
Certainly not as nice as Haskell which will essentially do all of this for you. But, that's where the trade-off lies.
Haskell uses the Hindley-Milner type inference. This kind of type-inference is powerful, but limits the type system of the language. Supposedly, for instance, subclassing doesn't work well with H-M.
At any rate, Scala type system is too powerful for H-M, so a more limited kind of type inference must be used.
I think the reason Scala requires the type annotation on the parameters of a newly defined function comes from the fact that Scala uses a more local type inference analysis than that used in Haskell.
If all your classes mixed in a trait, say Addable[T], that declared the + operator, you could write your generic add function as:
def add[T <: Addable[T]](x : T, y : T) = x + y
This restricts the add function to types T that implement the Addable trait.
Unfortunately, there is not such trait in the current Scala libraries. But you can see how it would be done by looking at a similar case, the Ordered[T] trait. This trait declares comparison operators and is mixed in by the RichInt, RichFloat, etc. classes. Then you can write a sort function that can take, for example, a List[T] where [T <: Ordered[T]] to sort a list of elements that mix in the ordered trait. Because of implicit type conversions like Float to RichFloat, you can even use your sort function on lists of Int, or Float or Double.
As I said, unfortunately, there is no corresponding trait for the + operator. So, you would have to write out everything yourself. You would do the Addable[T] trait, create AddableInt, AddableFloat, etc., classes that extend Int, Float, etc. and mix in the Addable trait, and finally add implicit conversion functions to turn, for example, and Int into an AddableInt, so that the compiler can instantiate and use your add function with it.
The function itself will be pretty straightforward:
def add(x: T, y: T): T = ...
Better yet, you can just overload the + method:
def +(x: T, y: T): T = ...
There's a missing piece, though, which is the type parameter itself. As written, the method is missing its class. The most likely case is that you're calling the + method on an instance of T, passing it another instance of T. I did this recently, defining a trait that said, "an additive group consists of an add operation plus the means to invert an element"
trait GroupAdditive[G] extends Structure[G] {
def +(that: G): G
def unary_- : G
}
Then, later, I define a Real class that knows how to add instances of itself (Field extends GroupAdditive):
class Real private (s: LargeInteger, err: LargeInteger, exp: Int) extends Number[Real] with Field[Real] with Ordered[Real] {
...
def +(that: Real): Real = { ... }
...
}
That may be more than you really wanted to know right now, but it does show both how to define generic arguments and how to realize them.
Ultimately, the specific types aren't required, but the compiler does need to know at least the type bounds.
Related
Is there a way to use shorter syntax when using context-bound type parameters? At the moment I have something like this
case class Vector2D[a : Numeric](x: a, y: a) {
val numA = implicitly[Numeric[a]]
def length2 = numA.plus(numA.times(x, x), numA.times(y, y))
}
and it makes more complex formulae unreadable.
Try this REPL session:
scala> case class Vector2D[T : Numeric](x: T, y: T) {
val numeric = implicitly[Numeric[T]]
import numeric._
def length2 = (x*x)+(y*y)
}
defined class Vector2D
scala> Vector2D(3,4).length2
res0: Int = 25
This is because Numeric contains an implicit conversion called mkNumericOps which you can import as shown above. If it didn't come out of the box, the way you could roll this yourself would be something like:
scala> implicit class NumericOps[T](val x: T) extends AnyVal { def +(y: T)(implicit n: Numeric[T]): T = n.plus(x, y)
| def *(y: T)(implicit n: Numeric[T]): T = n.times(x, y)
| }
defined class NumericOps
scala> case class Vector2D[a : Numeric](x: a, y: a) { def length2 = (x*x)+(y*y) }
defined class Vector2D
scala> Vector2D(3,4).length2
res0: Int = 25
If you make NumericOps not a value class (don't extend AnyVal) then the implicit Numeric can go on the constructor instead of each method, which might be better, or not really matter.
Anyway there's no need to write your own since Numeric already has mkNumericOps.
These "ops" classes are called the "enrich my library" pattern.
Numeric.Ops is here
and the implicit being imported to auto-create it is mkNumericOps on Numeric, here.
Just
import Numeric.Implicits._
then for every type that for which an implicit Numeric can be found
(importing just the NumericOps conversion of one Numeric instance as suggested by #Havoc P gives you finer control as to for which types operations are available, but most of the time, Numeric.Implicits should be fine)
On the more general question is there a shorter syntax when using context bounds type parameters: in general, there is not. It is up to the typeclass to provide some sugar to make it easy to use, as Numeric does here.
For instance, it is more or less customary to have an apply method in the companion object which makes getting the instance a little easier than with implicitly
object Ordering {
def apply[T](implicit ord: Ordering[T]): Ordering[T] = implicitly[Ordering[T]]
}
so that you can get the implicit just with e.g Ordering[Int], rather than implicitly[Ordering[Int]].
Is it possible to define a parameter x in a method, such that the type of x is a generic type T that implements a given function signature (let us say def apply() : Double), without introducing a new type?
[Example] The goal is to define something like (I am using an adhoc syntax just for the sake of illustration):
def foo(x : T with def apply() : Double) = { ... }
Currently, I could introduce a new type ApplyDouble, but that would require me extending all possible types whose instances are legal parameters to 'foo', and foo's signature would then be turned into
def foo(x : ApplyDouble) = { ... }
Sure, it's possible with a structural type, and you've even almost got the syntax right:
def foo(x: { def apply(): Double }) = x.apply
And then:
scala> foo(() => 13.0)
res0: Double = 13.0
Or:
scala> foo(new { def apply() = 42.0 })
res1: Double = 42.0
The definition of foo will give you a warning about reflective access, which you can avoid by adding an import or compiler option (as described in the warning message).
Note that there is some overhead involved in calling methods on a structural type, so if you need this in a tight inner loop you may want to rethink your approach a bit. In most cases, though, it probably won't make a noticeable difference.
Good day!
I'm quite new to scala, so during development the following question was raised:
I want to describe class Tree[T], where T is type parameter.
But T should be constrainted - it should have 2 methods:
def key(): A, where A is some type, derived from method's implementation (!)
and def union(x: T): T, where T is the same as type parameter.
I suppose this constraint can be expressed in several ways:
defining two traits one with method key and other with method union (two traits is because of independent nature of these methods)
using structural subtyping
something else...
So how can I do it in each way? and do other ways exist?
Also it'll be good if it'll be easy to add these methods for simple types (like String, Int, etc).
You could define a structural type for key, but not for union. A structural type may not refer to abstract types defined outside itself. So this won't work:
trait Tree[T <: { def union(x: T): T }]
You may define a trait that elements of Tree must make available, though:
trait TreeVal[T] {
type A
def key: A
def union(x: T): T
}
This can be used two ways. First, the classes must implement that interface, which puts a serious constrain on what classes can be used as keys. This would be like this:
trait Tree[T <: TreeVal[T]]
It could also be offered as an implicit conversion, like this:
class IntVal(v: Int) extends TreeVal[Int] {
type A = Int
def key: A = v
def union(x: Int): Int = x + v
}
implicit def IntIsVal(v: Int): IntVal = new IntVal(v)
class Tree[T <% TreeVal[T]] // must be class, so it can receive parameters
This used what is called a view bound. Look that up for more information, but suffice to say you'll be able to treat anything that has an implicit conversion defined and in scope as if it were a TreeVal. For example:
class Tree[T <% TreeVal[T]](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) {
override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), node.key, right.getOrElse("o"))
}
Alternatively, you can use it with the type class pattern, with a few changes:
trait TreeVal[T] {
type A
def key(v: T): A
def union(x: T, y: T): T
}
class Tree[T : TreeVal] // must be class, so it can receive parameters
The type class pattern uses context bounds. Look that up for more information. This style is generally preferred over the former style nowadays, because it is more flexible in a number of ways. Nevertheless, both will work.
In this case, one would use it like this:
implicit object IntVal extends TreeVal[Int] {
type A = Int
def key(v: Int) = v
def union(x: Int, y: Int) = x + y
}
class Tree[T: TreeVal](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) {
val treeVal = implicitly[TreeVal[T]]
import treeVal._
override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), key(node), right.getOrElse("o"))
}
If you want to be able to “add” these methods to simple types, maybe you'd be better off using type classes. Read more about type classes in this question, and look at Kevin Wright's answer, which shows how to “add” a zero and an append method to Int and String.
Structural types are implemented with Java reflection, so they will decrease performances. It's ok for script-like short programs, or for initialization, but any intensive usage may bring you program to its knees...
So I'll choose you first option. You'll need at least two type parameters. But you can go with only one trait, if you don't need a finer granularity:
trait Tree[T,A] {
def key(): A
def union( x: T ): T
}
I have read the answer to my question about scala.math.Integral but I do not understand what happens when Integral[T] is passed as an implicit parameter. (I think I understand the implicit parameters concept in general).
Let's consider this function
import scala.math._
def foo[T](t: T)(implicit integral: Integral[T]) { println(integral) }
Now I call foo in REPL:
scala> foo(0)
scala.math.Numeric$IntIsIntegral$#581ea2
scala> foo(0L)
scala.math.Numeric$LongIsIntegral$#17fe89
How does the integral argument become scala.math.Numeric$IntIsIntegral and scala.math.Numeric$LongIsIntegral ?
The short answer is that Scala finds IntIsIntegral and LongIsIntegral inside the object Numeric, which is the companion object of the class Numeric, which is a super class of Integral.
Read on for the long answer.
Types of Implicits
Implicits in Scala refers to either a value that can be passed "automatically", so to speak, or a conversion from one type to another that is made automatically.
Implicit Conversion
Speaking very briefly about the latter type, if one calls a method m on an object o of a class C, and that class does not support method m, then Scala will look for an implicit conversion from C to something that does support m. A simple example would be the method map on String:
"abc".map(_.toInt)
String does not support the method map, but StringOps does, and there's an implicit conversion from String to StringOps available (see implicit def augmentString on Predef).
Implicit Parameters
The other kind of implicit is the implicit parameter. These are passed to method calls like any other parameter, but the compiler tries to fill them in automatically. If it can't, it will complain. One can pass these parameters explicitly, which is how one uses breakOut, for example (see question about breakOut, on a day you are feeling up for a challenge).
In this case, one has to declare the need for an implicit, such as the foo method declaration:
def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
View Bounds
There's one situation where an implicit is both an implicit conversion and an implicit parameter. For example:
def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
getIndex("abc", 'a')
The method getIndex can receive any object, as long as there is an implicit conversion available from its class to Seq[T]. Because of that, I can pass a String to getIndex, and it will work.
Behind the scenes, the compile changes seq.IndexOf(value) to conv(seq).indexOf(value).
This is so useful that there is a syntactic sugar to write them. Using this syntactic sugar, getIndex can be defined like this:
def getIndex[T, CC <% Seq[T]](seq: CC, value: T) = seq.indexOf(value)
This syntactic sugar is described as a view bound, akin to an upper bound (CC <: Seq[Int]) or a lower bound (T >: Null).
Please be aware that view bounds are deprecated from 2.11, you should avoid them.
Context Bounds
Another common pattern in implicit parameters is the type class pattern. This pattern enables the provision of common interfaces to classes which did not declare them. It can both serve as a bridge pattern -- gaining separation of concerns -- and as an adapter pattern.
The Integral class you mentioned is a classic example of type class pattern. Another example on Scala's standard library is Ordering. There's a library that makes heavy use of this pattern, called Scalaz.
This is an example of its use:
def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
There is also a syntactic sugar for it, called a context bound, which is made less useful by the need to refer to the implicit. A straight conversion of that method looks like this:
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Context bounds are more useful when you just need to pass them to other methods that use them. For example, the method sorted on Seq needs an implicit Ordering. To create a method reverseSort, one could write:
def reverseSort[T : Ordering](seq: Seq[T]) = seq.reverse.sorted
Because Ordering[T] was implicitly passed to reverseSort, it can then pass it implicitly to sorted.
Where do Implicits Come From?
When the compiler sees the need for an implicit, either because you are calling a method which does not exist on the object's class, or because you are calling a method that requires an implicit parameter, it will search for an implicit that will fit the need.
This search obey certain rules that define which implicits are visible and which are not. The following table showing where the compiler will search for implicits was taken from an excellent presentation about implicits by Josh Suereth, which I heartily recommend to anyone wanting to improve their Scala knowledge.
First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Same scope in other files
Now look at associated types in
Companion objects of a type
Companion objects of type parameters types
Outer objects for nested types
Other dimensions
Let's give examples for them.
Implicits Defined in Current Scope
implicit val n: Int = 5
def add(x: Int)(implicit y: Int) = x + y
add(5) // takes n from the current scope
Explicit Imports
import scala.collection.JavaConversions.mapAsScalaMap
def env = System.getenv() // Java map
val term = env("TERM") // implicit conversion from Java Map to Scala Map
Wildcard Imports
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Same Scope in Other Files
This is like the first example, but assuming the implicit definition is in a different file than its usage. See also how package objects might be used in to bring in implicits.
Companion Objects of a Type
There are two object companions of note here. First, the object companion of the "source" type is looked into. For instance, inside the object Option there is an implicit conversion to Iterable, so one can call Iterable methods on Option, or pass Option to something expecting an Iterable. For example:
for {
x <- List(1, 2, 3)
y <- Some('x')
} yield, (x, y)
That expression is translated by the compile into
List(1, 2, 3).flatMap(x => Some('x').map(y => (x, y)))
However, List.flatMap expects a TraversableOnce, which Option is not. The compiler then looks inside Option's object companion and finds the conversion to Iterable, which is a TraversableOnce, making this expression correct.
Second, the companion object of the expected type:
List(1, 2, 3).sorted
The method sorted takes an implicit Ordering. In this case, it looks inside the object Ordering, companion to the class Ordering, and finds an implicit Ordering[Int] there.
Note that companion objects of super classes are also looked into. For example:
class A(val n: Int)
object A {
implicit def str(a: A) = "A: %d" format a.n
}
class B(val x: Int, y: Int) extends A(y)
val b = new B(5, 2)
val s: String = b // s == "A: 2"
This is how Scala found the implicit Numeric[Int] and Numeric[Long] in your question, by the way, as they are found inside Numeric, not Integral.
Companion Objects of Type Parameters Types
This is required to make the type class pattern really work. Consider Ordering, for instance... it comes with some implicits in its companion object, but you can't add stuff to it. So how can you make an Ordering for your own class that is automatically found?
Let's start with the implementation:
class A(val n: Int)
object A {
implicit val ord = new Ordering[A] {
def compare(x: A, y: A) = implicitly[Ordering[Int]].compare(x.n, y.n)
}
}
So, consider what happens when you call
List(new A(5), new A(2)).sorted
As we saw, the method sorted expects an Ordering[A] (actually, it expects an Ordering[B], where B >: A). There isn't any such thing inside Ordering, and there is no "source" type on which to look. Obviously, it is finding it inside A, which is a type parameter of Ordering.
This is also how various collection methods expecting CanBuildFrom work: the implicits are found inside companion objects to the type parameters of CanBuildFrom.
Outer Objects for Nested Types
I haven't actually seen examples of this. I'd be grateful if someone could share one. The principle is simple:
class A(val n: Int) {
class B(val m: Int) { require(m < n) }
}
object A {
implicit def bToString(b: A#B) = "B: %d" format b.m
}
val a = new A(5)
val b = new a.B(3)
val s: String = b // s == "B: 3"
Other Dimensions
I'm pretty sure this was a joke. I hope. :-)
EDIT
Related questions of interest:
Context and view bounds
Chaining implicits
The parameter is implicit, which means that the Scala compiler will look if it can find an implicit object somewhere that it can automatically fill in for the parameter.
When you pass in an Int, it's going to look for an implicit object that is an Integral[Int] and it finds it in scala.math.Numeric. You can look at the source code of scala.math.Numeric, where you will find this:
object Numeric {
// ...
trait IntIsIntegral extends Integral[Int] {
// ...
}
// This is the implicit object that the compiler finds
implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering
}
Likewise, there is a different implicit object for Long that works the same way.
Hi I am new to scala and trying to write addition program in with generic type parameter as shown below
object GenericTest extends Application {
def func1[A](x:A,y:A) :A = x+y
println(func1(3,4))
}
But this does not work .What mistake i am making .
A could be any type in this case. x + y means x.+(y), which would only compile if either a) the type A had a method +, or b) the type A was implicitly convertible to a type with a method +.
The type scala.Numeric provides the ability to write code that abstracts over the numeric system -- it could be called with Double, Int, or even your own exotic numeric system, such as complex numbers.
You can add an implicit parameter to your method of type Numeric[A].
object GenericTest extends Application {
def func1[A](x: A, y: A)(implicit n: Numeric[A]): A = x + y
}
In Scala 2.8, this can be shortened:
object GenericTest extends Application {
def func1[A: Numeric](x: A, y: A): A = x + y
}
Go to Scala: How to define “generic” function parameters? for what you want.