I am using some functions that return Options, but I would like to replace them by PartialFunctions in order to use the collect function in Scala. In detail I am trying to call collect (and collectFirst) on a list of objects that contain a partial function in the following way:
class A(val bs : List[B]) {
def getAll(i : Int): List[Int] = bs.map(_.foo(i))
}
class B(val y : Int) {
val foo : PartialFunction[Int, Int] = {
case x if x > y => y
}
}
The above code compiles and does what I want to if the function foo is defined for all values in bs.
val a = new A(List(new B(1), new B(2), new B(3)));
println(a.getAll(5))
prints "List(1, 2, 3)", but of course I run into an error if foo is not defined for a value. Hence, I want to replace it by "collect"
def getAll(i : Int): List[Int] = bs.collect(_.foo(i))
In my understanding collect should work pretty much the same as map, yet still the above code does not compile (I get a type mismatch because foo cannot be resolved). What is the best way in this case?
collect expects to receive a partial function (not a function or lambda), that will take an element of your collection as an input: PartialFunction[B, Int]. But here you want just to call your PartialFunction[Int, Int] inside another function, so you don't even passing a PartialFunction into collect (you're passing function (_.foo(i)): B => Int).
Solution without collect (but still with PartialFunction as a member of B):
def getAll(i : Int): List[Int] = bs.flatMap(_.foo.lift(i))
lift rises your function from PartialFunction[Int, Int] to Int => Option[Int] here.
If you really really want to collect:
import Function._
def getAll(i : Int): List[Int] = bs.collect(unlift(_.foo.lift(i)))
unlift reduces B => Option[Int] into PartialFunction[B, Int]
The ugliest version is collect{ case x if x.foo.isDefinedAt(i) => x.foo(i) }
Better solution is to move your partial function outside of B:
case class A(bs : List[B]) {
def getAll(x : Int): List[Int] = bs.collect {
case B(y) if x > y => y
}
}
case class B(val y : Int)
Related
It is my understanding that a Dictionary's elements must all be the same (ie: unit -> unit)
I need a way to add functions to an object, similar to a Dictionary, but my problem is that the functions have different Types. The only thing I can know for sure is that added functions will always follow a pattern of int -> 'T where 'T could be any Type. All functions in the object could be made to inherit from a shared type if needed. Here is a non-functioning example of how it would be used.
let myFunctions = Dictionary<int,int -> unit>()
let exampleFunction0 (x : int) : int = x + 1
let exampleFunction1 (x : int) : byte = (byte)x
let exampleFunction2 (x : int) : string[] = Array.create<string> 1 "test"
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x = myFunctions.Item(randomNumber) x
It is important to note that which one of the functions that gets called is random and I cannot know it. The purpose of the dictionary is to hold the functions that will be called randomly. As in the examples, the results are not the same as I need the results to be different for each function. x will always be the same, but the result of the function will not.
The code will be in a library to be reused, so functions may be added that I will never see.
You need to unify the output types to make this work.
If all the types are known you should use a Discriminated Union.
type ReturnValues =
| Case0 of int
| Case1 of byte
| Case2 of string[]
let myFunctions = Dictionary<int,int -> ReturnValues>()
let exampleFunction0 (x : int) = x + 1 |> Case0
let exampleFunction1 (x : int) = (byte)x |> Case1
let exampleFunction2 (x : int) = Array.create<string> 1 "test" |> Case2
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x : ReturnValues = myFunctions.Item(randomNumber) x
If you don't know all the types you can make all the return types obj (Dictionary<int,int -> obj>) using the box function or you can make all the return types implement a common interface.
What has ultimately solved the problem for me is to package together the Type and Object. This package is what the functions that will be added to the dictionary must return. This way there is a standard way for new types to be added after compilation.
open System.Collections.Generic
open System
// a package that can hold an object and its type
type package(x, y) =
member this.x : Type = x
member this.y : Object = y
//empty class for testing
type testClass() = class end
//custom types for testing
type fiy(x) =
member this.Value : string = x
type foe(x) =
member this.Value : testClass = x
//functions for testing
let func0 (x: int) : package = package(typeof<int>, x)
let func1 (x: int) : package = package(typeof<fiy>, fiy("potato"))
let func2 (x: int) : package = package(typeof<foe>, foe(testClass()))
let myFunctions = Dictionary<int, (int -> package)>()
//example use of adding a function
myFunctions.Add(0, (func0))
myFunctions.Add(1, (func1))
myFunctions.Add(2, (func2))
//pick a random number to test with; as we will have no idea which function will be ran
let randomNumber = System.Random().Next(3)
let pickedFunction x : package = (myFunctions.Item(randomNumber) x)
let ranFunction = pickedFunction 5 //just some filler number to test with
printfn "The type of the ranFunction is: %s" (ranFunction.x.ToString())
I'm learning Scala and in a book that I'm reading (Functional Programming in Scala) I came across an example of a custom List implementation in Scala which goes like this:
sealed trait MyList[+A]
case object MyNil extends MyList[Nothing]
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A]
object MyList {
def apply[A](as: A*): MyList[A] =
if (as.isEmpty) MyNil
else Cons(as.head, apply(as. tail: _*))
}
I would like to extend MyList to add the following functionality:
add a tail method that returns all elements of a MyList instance without the first one, e.g. val x = MyList(1,2,3); x.tail == MyList(2,3).
Add a sum method that is only applicable when MyList contains Ints (or even better for all numeric types). So e.g. val x = MyList(1,2,3); x.sum == 6
The idea above 2 questions is to understand: (1) how to interact with the instance of my class and (2) how to use polymorphism in a situation like this. After some searching around, I'm not even sure how to begin with these problems, which is why I'm asking this question.
Any tips would be appreciated. Many thanks!
UPDATE:
A few updates:
First, I'd like to point out that the solution to the programming challenges in the Functional Programming course that I mentioned earlier can be found here, however, I'm looking for something a little different than what the author is asking for.
I've managed to find an answer to my first question "how can I use tail on my instance itself, e.g. MyList(1,2,3).tail?". To solve this, I had to modify the original trait in the following manner:
sealed trait MyList[+A] {
def tail: MyList[A] = MyList.tail(this)
}
I'm not sure if this is the best way of doing what I want to do, but it works. If anyone has better suggestions, please let me know.
The second part is harder. I wanted to add the following inside the same trait:
def sum[Int]: MyList[Int] = MyList.sum(this)
But IntelliJ is complaining about the type of this which is A and I need to apply this conditionally on this being of type Int.
Another alternative is to do the following:
def sum: Int = this match {
case x: MyList[Int] => MyList.sum(x)
}
But what if we want to create another implementation for String that will also return a String? This cannot be the right solution and I haven't found one yet. Please help :)
.tail
I note that your Cons class already has a public tail member. I'd be tempted to start there and just make it universal...
sealed trait MyList[+A] {
def tail: MyList[A]
}
...and add the MyNil implementation.
case object MyNil extends MyList[Nothing] {
def tail: MyList[Nothing] =
throw new java.lang.UnsupportedOperationException("tail of empty list")
}
This is how the standard library List handles the tail of an empty list. Another, perhaps gentler, option would be to return this so that the tail of an empty MyList is just the empty MyList.
Leaving class Cons and object MyList unchanged, we get the expected results.
MyList('s','h','o','w').tail //res0: MyList[Char] = Cons(h,Cons(o,Cons(w,MyNil)))
MyList(9).tail.tail //java.lang.Unsupported...
.sum
This is a bit trickier. We want each .sum invocation to compile only if the elements are of a sum-able type, such as Int. The Scala way to achieve this to require that the call site provide implicit "evidence" that the element type is acceptable.
sealed trait MyList[+A] {
def sum(implicit ev : A =:= Int) : Int //can sum only if A is Int
}
Alas, this won't compile because MyList is covariant on A, but being the type of a passed parameter puts A in a contra-variant position.
Error: covariant type A occurs in invariant position in type A =:= Int of value ev
Fortunately there's a fix for that: use a different type parameter, related to A but not restricted to its covariant relationship.
sealed trait MyList[+A] {
def sum[B >: A](implicit ev : B =:= Int) : Int = 0 //default behavior
}
case object MyNil extends MyList[Nothing] { ... //unchanged
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A] {
override def sum[B >: A](implicit ev :B =:= Int) : Int = head + tail.sum[B]
}
object MyList { ... //unchanged
MyList(23,31,12).sum //res0: Int = 66
MyList("as","is").sum //won't compile
Numeric[A]
Well that works for Int, but it would be a pain to have to do the same for every sum-able type. Fortunately the standard library offers the Numeric typeclass which provides some basic values (zero and one) and operations (plus(), minus(), times(), etc.) for all the numeric types under its umbrella (Short, Long, Float, etc.).
So, putting it all together:
sealed trait MyList[+A] {
val tail: MyList[A]
def sum[B >: A](implicit ev : Numeric[B]): B = ev.zero
}
case object MyNil extends MyList[Nothing] {
val tail: MyList[Nothing] = this
}
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A] {
override def sum[B >: A](implicit ev : Numeric[B]): B = ev.plus(head, tail.sum[B])
}
object MyList {
def apply[A](as: A*): MyList[A] =
if (as.isEmpty) MyNil else Cons(as.head, apply(as.tail: _*))
}
I have defined an interface A to be used by several functors, and notably by MyFunctor :
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
Now I want to define a module B with implements the interface A. In particular, the implementation of complex_func should use basic_func through complex_impl in MyFunctor :
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
However, this code doesn't compile as B is not fully declared in the context of MyFunctor(B). Obviously B depends on MyFunctor(B), which itself depends on B, so I tried to use the rec keyword on module B, but it didn't work out.
So, is it possible to do something like this ? It would be useful as I have several modules B_1, ..., B_n that use the same implementation of B_k.complex_func in terms of B_k.basic_func.
Or is there a better pattern for my problem ? I know that I can declare complex_impl as a regular function taking basic_func as a parameter, without using a functor at all :
let complex_impl basic_func params =
...
basic_func ...
...
But in my case complex_impl uses many basic functions of A, and I think that the paradigm of functors is clearer and less error-prone.
Edit : I followed this answer, but in fact, A uses some type t that is specialized in B :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
And now I get the error (for x at line Impl.complex_impl x) :
This expression has type t = int but an expression was expected of type B.t
Edit 2 : I solved this second problem with the following code :
module rec B :
A with type t = int
= struct
type t = int
...
end
You can use recursive modules just like you'd write recursive let bindings
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
Note (a) the module rec bit in the definition of B and (b) that I am required to provide a module signature for a recursive module definition.
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
There's a small caveat, however, in that this only works because the signature A has only values which are function types. It is thus known as a "safe module". If basic_func and complex_func were values instead of function types then it would fail upon compilation
Error: Cannot safely evaluate the definition
of the recursively-defined module B
I'm coming from C++ and trying to wrap my head around scala's type system.
Consider the following C++ template class:
template<class T>
class Point2
{
Point2( T x, T y ) :
x(x),
y(y)
{}
T x;
T y;
Point2<T> operator+( Point<T> const& other ) const
{
return Point<T>(x+other.x, y+other.y);
}
T sumComponents() const { return x+y; }
}
Point2<Double> p0(12.3, 45.6)
Point2<Double> p1(12.3, 45.6)
Point2<Double> p = p1+p2
Double d = p1.sumComponents()
I'm finding I want to write something like this:
case class Point2[ T ] (x:T, y:T) {
def +() Point2[T]: = x+y
def sumComponents() T: = x+y
}
or, (because the compile has problems with this),
trait Addable[T] { // Require T supports the + operatory
def +( that:T ):T
}
case class Point2[ T<:Addable[T] ] (x:T, y:T) {
def +() Point2[T]: = x+y
def sumComponents() T: = x+y
}
which is similarly problematic because I can't require Double to extend Addable.
Generally, I'm finding it scala's type system works with a set of constraints that I don't quite understand.
What's the idiomatic way of implementing the above in scala?
And what's the right way for C++ template programmers to understand the limits of generics in scala? (why can't I do this in scala? e.g. Is it because generics are compiled before being instaniated?)
What's the idiomatic way of implementing the above in scala?
Either by specifying appropriate requirements of T, or using type classes to provide the desired behavior. I'll get back to this later.
And what's the right way for C++ template programmers to understand
the limits of generics in scala? (why can't I do this in scala? e.g.
Is it because generics are compiled before being instaniated?)
C++ templates are compiled "at" the usage site, and different code is generated for each combination of parameters to the templates. So if you use the class above with int and double, you get two different Point2 classes compiled.
Basically, C++ templates are macros, though nowhere near as dumb as #define macros. In fact, C++ templates are turing complete. Maybe it will be possible to accomplish something equivalent in the future, with the upcoming macro capabilities planned for Scala 2.11 and beyond, but let's ignore that for now.
Type parameters (Scala equivalent of Java generics) do not change how a code is compiled. A parameterized class generates its bytecode when it is compiled, not when it is used. So, by the time one instantiates a Point2 with Double, it is too late to generate bytecode.
That means that the code generated by a parameterized class must be compatible with all types a class can be instantiated with.
And that's the source of the trouble: any methods called on T must be known to be present on T at the time Point2 is compiled. Therefore, T must be defined to have an upper boundary of traits or classes that define such methods, as you have shown in your example.
Of course, that is not always possible, as you rightly pointed out, and that's where type classes come in. A type class is a set of types for which a set of behaviors is defined. Type classes, as implemented in Scala, are defined as classes whose instances define the behavior of other classes.
In the example you gave, you'd be using either the Numeric type class, or the Fractional type class if you need fractional division as well. A simple example of type class use is:
scala> import scala.math.Numeric
import scala.math.Numeric
scala> def sum[T](x: T, y: T)(implicit num: Numeric[T]): T = num.plus(x, y)
sum: [T](x: T, y: T)(implicit num: scala.math.Numeric[T])T
Or, using a special notation called "context bounds",
scala> def sum[T : Numeric](x: T, y: T): T = implicitly[Numeric[T]].plus(x, y)
sum: [T](x: T, y: T)(implicit evidence$1: scala.math.Numeric[T])T
The notation T : Numeric can be read as T such that there's an implicit instance of Numeric[T] available. The code implicitly[X] returns an implicit value of type X if one can be found (or fails at compile time).
Now, notice how no method is called on x and y -- instead, we call methods on num whose class is Numeric[T]. The class Numeric[T] has a method plus which knows how to add two Ts.
Because what we need is type class instances, one can easily add new types to satisfy a type class. One could easily declare a Numeric type class for Point2 (assuming all its methods could be implemented):
class Point2Numeric[T](implicit num: Numeric[T]) extends Numeric[Point2[T]] {
def plus(x: Point2[T], y: Point2[T]): Point2[T] = x + y
// etc
}
implicit def ToPoint2Numeric[T : Numeric] = new Point2Numeric[T]
With that in place, then for any T for which there's a Numeric[T], there would be also a Numeric[Point2[T]].
After plain type inheritance (upper type bounds), type classes are the most common form of type constraint used in Scala. There are other forms a bit more sophisticated, for which there's some discussion whether they are type classes or something different -- the magnet pattern, for instance. Look at shapeless for an example of how far one can take such things.
Another kind of type constraint that used to be very common but is now being used more circumspectly are view bounds. I'll not go into details (in fact, search for context bounds and view bounds to find a long answer about it from myself), but they can be used to make type classes more readable when used. For example:
scala> import scala.math.Numeric.Implicits._
import scala.math.Numeric.Implicits._
scala> def sum[T : Numeric](x: T, y: T): T = x + y
sum: [T](x: T, y: T)(implicit evidence$1: scala.math.Numeric[T])T
The imported definitions contain implicit conversions that make it possible to use values of type T for which there's a Numeric[T] as if they, themselves, had the methods like + or -.
As a final note, it is important to realize this goes through many levels of indirection and, therefore, might not be very suitable for high performance code.
Simply, you can do something like this:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import math.Numeric
import math.Numeric.Implicits._
case class Point2[A: Numeric](x: A, y: A) {
def + (other: Point2[A]): Point2[A] =
Point2(this.x + other.x, this.y + other.y)
def sumComponents: A = x + y
}
// Exiting paste mode, now interpreting.
import math.Numeric
import math.Numeric.Implicits._
defined class Point2
scala> val p1 = Point2(1, 2)
p1: Point2[Int] = Point2(1,2)
scala> val p2 = Point2(3, 4)
p2: Point2[Int] = Point2(3,4)
scala> p1 + p2
res2: Point2[Int] = Point2(4,6)
scala> val p3 = Point2(1.2, 3.4)
p3: Point2[Double] = Point2(1.2,3.4)
scala> val p4 = Point2(1.6, 6.4)
p4: Point2[Double] = Point2(1.6,6.4)
scala> p3 + p4
res3: Point2[Double] = Point2(2.8,9.8)
scala>
I created a library template.scala. You can use the library to create C++ flavored templates, avoiding complicated implicits.
import com.thoughtworks.template
case class Point2[T](x:T, y:T) {
#template def +(rhs: Point2[_]) = Point2(x + rhs.x, y + rhs.y)
#template def sumComponents() = x + y
}
println(Point2(1, 3).sumComponents()) // Output: 4
println(Point2(1, 3) + Point2(100, 200)) // Output: Point2(101,203)
Note that you can even plus two Point2s with different component types.
println(Point2(1.5, 0.3) + Point2(100, 200)) // Output: Point2(101.5,200.3)
Even nested Point2:
// Output: Point2(Point2(10.1,20.2),Point2(101.0,202.0))
println(Point2(Point2(0.1, 0.2), Point2(1.0, 2.0)) + Point2(Point2(10, 20), Point2(100, 200)))
It works because #template functions are code templates that will inline at the call site.
This requires a type class (which I'm calling Addition) and an implicit conversion (which I'm defining via an implicit class called Op). In practice, you would use the Numeric type for this particular situation, but for the purpose of illustration, this is how you would define your own:
trait Addition[T] {
def add(a: T, b: T): T
implicit class Op(a: T) {
def +(b: T) = add(a, b)
}
}
implicit object IntAddition extends Addition[Int] {
def add(a: Int, b: Int) = a + b
}
implicit object DoubleAddition extends Addition[Double] {
def add(a: Double, b: Double) = a + b
}
case class Point2[T](x: T, y: T)(implicit addition: Addition[T]) {
import addition.Op
def +(p: Point2[T]): Point2[T] = Point2(x + p.x, y + p.y)
def sumComponents(): T = x + y
}
Use Numeric, available as an implicit.
import scala.math.Numeric;
case class Point2[T](x: T, y: T)(implicit num: Numeric[T])
Look at Numeric in the API, does what you need.
After a lot of Java and some Haskell I wanted to have a look at Scala. From the code below, I'm getting this error message
type mismatch; found : List[Nothing] => Option[Nothing] required: List[Int] => Option[Nothing]
I don't know what I'm doing wrong:
object MyFirstScalaObject {
def main(args: Array[String]) {
lazy val testValues:List[List[Int]] = List((1 to 10).toList, null, List());
println( testFunction(last, testValues));
}
def testFunction[I, O](f : I => O, inputs : List[I]):
List[(I, O)] =
inputs.zip(inputs.map(f));
def last[A](xs:List[A]):Option[A] = xs match {
case x::Nil => Some(x);
case _::xs => last(xs);
case _ => None;
}
}
Thanks for any advice.
Cheers,
because of the way type inference works in scala, it is unable to determine the what the type parameter to last has to be, so it has to take the overly conservative fallback guess that it is Nothing.
You can explicitly specify the types when you call testFunction:
testFunction[List[Int],Option[Int](last, testValues)
or you can document more fully the relationship between the type parameters in the testFunction declaration, which will give the type inferencer more information:
def testFunction[A, I[_], O[_]](f : I[A] => O[A], inputs : List[I[A]]): List[(I[A], O[A])]
This explicitly says that I and O are type constructors (kind * -> *), now that the input/output types of f are more specific, the inferencer can correctly infer that the A parameter to the the last function must be Int.
A fully revised & tested version, using senia's idea:
object MyFirstScalaObject {
def main(args: Array[String]) {
lazy val testValues = List((1 to 10).toList, null, List())
println(testFunction(testValues)(last))
}
def testFunction[I, O](inputs: List[I])(f: I => O): List[(I, O)] =
inputs.zip(inputs.map(f))
def last[A](xs: List[A]): Option[A] = xs match {
case x :: Nil => Some(x)
case _ :: xs => last(xs)
case _ => None
}
}
Type inference proceeds left-to-right; information from one parameter list is used within next parameter list.
In this code, when you call testFunction Scala can deduce I from the first parameter, then it can feed I as the input type of the function f to figure out its type (that is, that the argument last is applied with A = Int), then it finally gets the value of O from the return type of the function.
I can't tell you why type inference in scala works this way.
But there is common way to help compiler in such cases - parameter sections.
def testFunction[I, O](inputs : List[I])(f: I => O): List[(I, O)] = inputs.zip(inputs.map(f))
Usage:
testFunction(testValues)(last)
Similar solution is to add method testFunction to class List:
class LastsHelper[T](inputs: List[T]) {
def testFunction[O](f: T => O): List[(T, O)] = inputs.zip(inputs.map(f))
}
implicit def toLastsHelper[T](inputs: List[T]) = new LastsHelper(inputs)
You can use such methods like methods of List:
testValues.testFunction(last)