Restore a dependent type at runtime - scala

I'm trying to restore a dependent type in Scala at runtime. I basically want to archive a type-save map, where every key has an associated type, but all type informations of the stored key value pairs aren't visible to the user of Map (unlike the awesome Shapeless Map).
class Key[V] {
type Value = V
def ->(value: V) = Pair(this, value)
}
trait Pair {
val key: Key[_]
val value: key.Value
}
trait Map {
val pairs: Seq[Pair]
def get[V](key: Key[V]): Option[V] =
pairs.find(pair => pair.key eq key).map(_.value).asInstanceOf[Option[V]]
// ^ ^
// the runtime prove that pair.key.Value equals V |
// |
// 'Convince' the compile that I know what I do
}
Usage:
val text = new Key[String]
val count = new Key[Int]
val map: Map = new Map { val pairs = text -> "Hello World!" :: Nil }
map.get(text) // Some(Hello World!), Type: Option[String]
map.get(count) // None, Type: Option[Int]
Is it possible to write a get method without using a cast explicit with asInstanceOf or implicit with a match with an unchecked branch?
I tried to write an unapply for pairs, but run into the same problem.
Note that I leave out the definition of the Pair-companion object. Here a running example in a Gist.

Remember the JVM erases generics at runtime. So anything that relies on generics, including dependent typing, can only happen at compile time - i.e. in the caller, because any given method will only compile to one runtime code path. The only alternative is checking the runtime class (either directly or by pattern matching) as you say. (Shapeless has a type-safe, typeclass-driven helper if you go down that route)
There might be a clever way to express your requirements without the type issues, but in general the type information has to be either visible to the caller or checked at runtime.

Many way to solve your type issue. First of all define source of issue:
trait Map {
val pairs: Seq[Pair] // (1)
def get[V](key: Key[V]): Option[V] = // (2)
pairs.find(_.key eq key).map{_.value } // (3)
}
pairs type is Seq of Pair (with some embedded undefined type key: Key[_])
key type is Key[V] and expected result type is Option[V]
try to return type from (1) Key[_] instead of expected Key[V] and extracted V
Solution: you should guaranty that pairs embedded type of key is the same what you return
One of possible solutions:
trait Key[V] {
def ->(value: V) = Pair(this, value)
}
trait Pair {
type Value
val key: Key[Value]
val value: Value
}
trait Map1[V] {
val pairs: Seq[Pair {type Value = V } ]
def get(key: Key[V]): Option[V] =
pairs.find(_.key eq key).map{ _.value }
}
trait Map2 {
type Value
val pairs: Seq[Pair {type Value = Map2.this.Value} ]
def get[V >: Map2.this.Value](key: Key[V]): Option[V] =
pairs.find(_.key eq key).map{ _.value }
}

Related

Scala HashMap#contains expects Nothing

I am trying to use a Scala HashMap like below, and when I try to operate on the HashMap, I get type mismatches. Besides using Java HashMap, how can I write this?
import scala.collection.mutable._
object Solution {
def twoSum(nums: Array[Int], target: Int): Array[Int] = {
var lookupTable = new HashMap()
for(i <- nums.indices) {
if (lookupTable.contains(target - nums(i)))
return Array(lookupTable(i), i)
lookupTable.put(nums(i), i)
}
throw new Exception
}
}
In the absence of a type ascription, an empty HashMap is a HashMap[Nothing, Nothing], which, because mutable HashMaps are invariant means you have a collection which you can't put anything into or get anything out of.
There are thus two ways to fix this:
You can use a mutable HashMap[Int, Int]:
val lookupTable = HashMap[Int, Int]()
Alternatively, you can use an immutable HashMap, which is covariant in the value type and technically invariant in the key type, but there's a way around that:
var lookupTable = scala.collection.immutable.HashMap()
for (i <- nums.indices) {
if (lookupTable.contains(target - nums(i))) return Array(lookupTable(i), i)
else lookupTable = lookupTable ++ Seq((nums(i), i))
}

Scala: recursive value listHuman needs type

Why is this function giving me the following error:
recursive value listHuman needs type
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).filterNot(a=>listHuman.contains(a))}
return listHuman
}
I tried to do this, but it gives me another error:
val listHuman: List[Human] = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post)).get}.filterNot(human=>listHuman.contains(human))
forward reference extends over definition of value listHuman
This error means that constant value or variable is used before its declaration. For example
val y = x + 2
val x = 5
What wrong with your code is you try to define constant value with itself. It's impossible by definition of constant. To build recursion use def.
It seems like you want to do a foldLeft, does this work?
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
physicalResources.foldLeft(Set.empty[Human]) { (l, pr) =>
val applicableHuman = totalHumanResources.find(_.handles.contains(pr.post))
l ++ applicableHuman
}.toList
}
The premises here is to have setHumanResourcesreturn a unique/distint list of Human objects. The code tries this by doing filterNot(a=>listHuman.contains(a)) in definition of listHuman and thus recursively referring to listHuman while defining listHuman in semantically illegal way. This de-duping can be achieved properly by the following ways.
convert the List to Set and convert it back to List to remove duplicates like listHuman.toSet.ToList. for this method to work the Human object have property identity defined by overriding equals method. so the code will now look like
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr => totalHumanResources.find(_.handles.contains(pr.post))
listHuman.toSet.toList
}
A Demo for a sample class of Human is shown below.
scala> class Human(val firstName: String, val lastName: String) {
| override def toString = this.firstName
| override def equals(that: Any): Boolean = that match {
| case that: Human if that.firstName == this.firstName => true
| case _ => false
| }
| }
defined class Human
scala> List(new Human("Peter", "Parker"), new Human("Peter", "Quill")).toSet.toList
res14: List[Human] = List(Peter)
If the class Human cannot have object equality defined in it by overriding equals method then follow this approach. considering each Human can be uniquely identified by say two properties property1 and property2. the listHuman can be deduped by the following expression. For our previously defined Human class if we want to de-dupe on both firstName and lastName properties, the code would be like below.
listHuman.groupBy(x => (x.firstName, x.lastName)).map(_._2.head)
so the new method definition becomes
def setHumanResources(physicalResources: List[Physical], totalHumanResources: List[Human]): List[Human] = {
val listHuman = physicalResources.map{pr =>
totalHumanResources.find(_.handles.contains(pr.post))
listHuman.groupBy(x => (x.property1, x.property2) ).map(_._2.head)
}

Scala implicit for Option containing Map

I am trying to write the following implicit:
implicit class ExtractOrElse[K, V](o: Option[Map[K, V]]) {
def extractOrElse(key: K)(f: => V): V = { if (o.isDefined) o.get(key) else f }
}
Which I want to use in this way:
normalizationContexts.extractOrElse(shardId)(defaultNormalizationContext)
to avoid a clunkier syntax (normalizationContexts is an Option[Map[String, NormzalitionContext]]).
Also, let me add that it is intentional that there is only one default value: it will be used if the Option isEmpty, but if the Option isDefined, then the behavior of the Map is not changed, and it will throw an exception if the key is not found - so the default value won't be used in that case, and this is all intentional.
However, I get an error when passing in None in unit tests:
assertEquals(None.extractOrElse('a')(0), 0)
results in:
Error:(165, 37) type mismatch;
found : Char('a')
required: K
assertEquals(None.extractOrElse('a')(0), 0)
I realize that None is not parametric, as it is defined as:
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
What is the best way to make this work?
Instead of None.extractOrElse(...), try Option.empty[Map[Char, Int]].extractOrElse(...).
If you always use the same types for your test cases, you could also create a type alias in the specs class in order to reduce the clutter:
type OpMap = Option[Map[Char, Int]]
// ...
assertEquals(Option.empty[OpMap].extractOrElse('a')(0), 0)
Just in case, you can use flatMap and getOrElse to achieve the same thing without writing a new method:
val n = Option.empty[Map[String, Int]]
val s = Some(Map("x" → 1, "y" → 2))
n.flatMap(_.get("x")).getOrElse(3) // 3
s.flatMap(_.get("x")).getOrElse(3) // 1
s.flatMap(_.get("z")).getOrElse(3) // 3
The type system doesn't have enough information about the types K and V. There is no way to know what the type of A would be in the case where your None was Some[A].
When I create an example with explicit types, the code works as expected:
// Like this
val e = new ExtractOrElse(Option.empty[Map[Char, Int]])
e.extractOrElse('a')(0) // Equals 0
// Or like this
val e = new ExtractOrElse[Char, Int](None)
println(e.extractOrElse('a')(0))
// Or like this
val m: Option[Map[Char, Int]] = None
val e = new ExtractOrElse(m)
println(e.extractOrElse('a')(0))

Scala Erasure Type Match and Use in Different Method

I have been searching around to achieve this, even with Manifest and Reflect API, it's still hard to achieve.
With Manifest and Reflection, I can match List[Any] to a class(List[A]), I am also able to get match by type T, just as in
http://daily-scala.blogspot.co.uk/2010/01/overcoming-type-erasure-in-matching-1.html
How save a TypeTag and then use it later to reattach the type to an Any (Scala 2.10)
but how can I make sure the type of the input and use it in a method?
Say,
object test {
val list : List[List[Any]] = List(
List(2.5, 3.6 ,7.9),
List("EUR","HKD", "USD")
)
def calculateString(in:List[String]) = {
println("It's a String List")
println(in)
}
def calculateDouble(in:List[String]) = {
println("It's a Double List")
println(in)
}
def main( args: Array[String]){
list.foreach(l=> matchAndCalculate(l))
}
// Copy from Andrzej Jozwik it doesn't work, but it's good to demonstrate the idea
def matchAndCalculate(list:List[Any]) = list match {
case i if i.headOption.exists(_.isInstanceOf[Long]) => calculateLong(i)
case i if i.headOption.exists(_.isInstanceOf[String]) => calculateString(i)
}
}
Many Thanks
Harvey
PS: As Sarah pointed out that it might be the only way that keeping type manifest while I create the list in the first before I put them into more complex structure.
Here's the challenge: is that possible to cast List[Any] back to / match to something say List[String] and as input to method like def dummyMethod(stringList: List[String]) without pissing off compiler?
Unless you can change your data structure, Andrej's solution is the only reasonable way to do this.
You can't really use type manifests, because you have two levels of indirection. You'd need a different type manifest for every member of the outer list. E.g., you could have a List[(List[Any], TypeTag[Any])], but there's no way to get compile-time information about every individual row out of a List unless you build that information at the time that you're constructing the lists.
If you really wanted to carry along static type information, it would be easy to do this with implicits and just make each entry in your outer list a special class.
One simple variant might look like this:
class CalculableList[A](val elements: List[A])(implicit val calc: Calculator[A]) {
def calculate = calc(elements)
}
trait Calculator[-A] extends (List[A] => Unit)
implicit object StringCalc extends Calculator[String] {
def apply(in: List[String]) {
println("It's a String List")
println(in)
}
}
implicit object DoubleCalc extends Calculator[Double] {
def apply(in: List[Double]) {
println("It's a Double List")
println(in)
}
}
val list: List[CalculableList[_]] = List(
new CalculableList(List(1.0, 2.0, 3.0)),
new CalculableList(List("a", "b", "c"))
)
list foreach { _.calculate }
Another option for this kind of generic programming is to use Miles Sabin's Shapeless. This uses special data structures to let you construct arbitrary-sized tuples that can be treated like type-safe lists. It generates a data structure similar to a linked list with a generic type wrapper that keeps track of the type of each row, so you wouldn't want to use it unless your lists are fairly short. It's also a bit difficult to learn, maintain and understand—but it opens up some deep wizardry when you understand and use it appropriately.
I don't know enough about your use case to know whether Shapeless is advisable in this case.
In Shapeless for Scala 2.11, a solution would look something like this:
import shapeless._
val lists = List(1.0, 2.0, 3.0) ::
List("a", "b", "c") ::
HNil
object calc extends Poly1 {
implicit def doubleList = at[List[Double]] { in =>
println("It's a double list")
println(in)
}
implicit def stringList = at[List[String]] { in =>
println("It's a string list")
println(in)
}
}
lists map calc
def calculateString(in:List[String]) = {
println("It's a String List")
println(in)
}
def calculateDouble(in:List[Double]){
println("It's a Double List")
println(in)
}
def castTo[T](t:T,list:List[Any]) = list.asInstanceOf[List[T]]
def matchAndCalculate(list:List[Any]) = list.headOption match {
case Some(x:Double) => calculateDouble(castTo(x,list))
case Some(x:String) => calculateString(castTo(x,list))
}
And check:
scala> matchAndCalculate(List(3.4))
It's a Double List
List(3.4)
scala> matchAndCalculate(List("3.4"))
It's a String List
List(3.4)
scala> val list : List[List[Any]] = List(
| List(2.5, 3.6 ,7.9),
| List("EUR","HKD", "USD")
| )
list: List[List[Any]] = List(List(2.5, 3.6, 7.9), List(EUR, HKD, USD))
scala> list.foreach(l=> matchAndCalculate(l))
It's a Double List
List(2.5, 3.6, 7.9)
It's a String List
List(EUR, HKD, USD)

How do I use Scala Hashmaps and Tuples together correctly?

My code is as follows
import scala.collection.mutable.HashMap
type CrossingInterval = (Date, Date)
val crossingMap = new HashMap[String, CrossingInterval]
val crossingData: String = ...
Firstly why does the following line compile?
val time = crossingMap.getOrElse(crossingData, -1)
I would have thought -1 would have been an invalid value
Secondly how do I do a basic check such as the following
if (value exists in map) {
}
else {
}
In Java I would just check for null values. I'm not sure about the proper way to do it in Scala
Typing your code in the interpreter shows why the first statement compiles:
type Date = String
scala> val time = crossingMap.getOrElse(crossingData, -1)
time: Any = -1
Basically, getOrElse on a Map[A, B] (here B = CrossingDate) accepts a parameter of any type B1 >: B: that means that B1 must be a supertype of B. Here B1 = Any, and -1 is of course a valid value of type Any. In this case you actually want to have a type declaration for time.
For testing whether a key belongs to the map, just call the contains method. An example is below - since Date was not available, I simply defined it as an alias to String.
scala> crossingMap.contains(crossingData)
res13: Boolean = false
scala> crossingMap += "" -> ("", "")
res14: crossingMap.type = Map("" -> ("",""))
//Now "" is a map of the key
scala> crossingMap.contains("")
res15: Boolean = true
If you want to check whether a value is part of the map, the simplest way is to write this code:
crossingMap.values.toSet.contains("")
However, this builds a Set containing all values. EDIT: You can find a better solution for this subproblem in Kipton Barros comment.