Set, contains that returns match rather than boolean - scala

I went to the effort to create myself a class whereby I have an equals method that defines an equivalence relation for which the partition sets don't have size == 1.
The class takes an absolute path and a root (also a path), these "relative paths" are equivalent if their path relative to their roots are the same. I have two sets with these in and I have ensured that all the elements in each individual set have the same root. So, according to my logic there should be one or zero element(s() in the second set that == any element in the first set.
But now I realize that I don't have the nice O(1) lookup I wanted as the Set.contains() method only returns a boolean, not the element it found!! Is there a method or collection I'm not aware of that will give me the O(1) behaviour I'm looking for (i.e. an O(1) lookup on equals, returning the equal element.)

Redefining equality to mean something else than equality of all elements is almost always a bad idea. Scala sets assume that if two things are equal, they are interchangeable. This is not the case in your approach.
I think you will have to use a Map[T, T] instead of a Set[T] to do what you want.

This must surely have been asked before, but if so, I'm not able to find it.
There is a hole in the API here, as far as I can see.
Perhaps hope somebody can do better, but the best workaround I can find is:
def lookup[T](s: Set[T], x: T): Option[T] =
s.intersect(Set(x)).headOption
Let's take it for a spin. First define a case class that carries extra information that doesn't affect equality:
scala> case class C(x: Int)(val y: Int)
defined class C
scala> C(3)(5) == C(3)(6)
res4: Boolean = true
Now let's try a test case:
scala> val s = Set(C(3)(5), C(8)(2), C(7)(6))
s: scala.collection.immutable.Set[C] = Set(C(3), C(8), C(7))
scala> lookup(s, C(8)(99)).map(_.y)
res6: Option[Int] = Some(2)
Looks good.
As for whether it's O(1), it appears to me from perusing https://github.com/scala/scala/blob/2.11.x/src/library/scala/collection/immutable/HashSet.scala that it is.

Related

how to normalize a `scala.reflect.api.Types.Type`

How to implement the function normalize(type: Type): Type such that:
A =:= B if and only if normalize(A) == normalize(B) and normalize(A).hashCode == normalize(B).hashCode.
In other words, normalize must return equal results for all equivalent Type instances; and not equal nor equivalent results for all pair of non equivalent inputs.
There is a deprecated method called normalize in the TypeApi, but it does not the same.
In my particular case I only need to normalize types that represent a class or a trait (tpe.typeSymbol.isClass == true).
Edit 1: The fist comment suggests that such a function might not be possible to implement in general. But perhaps it is possible if we add another constraint:
B is obtained by navigating from A.
In the next example fooType would be A, and nextAppliedType would be B:
import scala.reflect.runtime.universe._
sealed trait Foo[V]
case class FooImpl[V](next: Foo[V]) extends Foo[V]
scala> val fooType = typeOf[Foo[Int]]
val fooType: reflect.runtime.universe.Type = Foo[Int]
scala> val nextType = fooType.typeSymbol.asClass.knownDirectSubclasses.iterator.next().asClass.primaryConstructor.typeSignature.paramLists(0)(0).typeSignature
val nextType: reflect.runtime.universe.Type = Foo[V]
scala> val nextAppliedType = appliedType(nextType.typeConstructor, fooType.typeArgs)
val nextAppliedType: reflect.runtime.universe.Type = Foo[Int]
scala> println(fooType =:= nextAppliedType)
true
scala> println(fooType == nextAppliedType)
false
Inspecting the Type instances with showRaw shows why they are not equal (at least when Foo and FooImpl are members of an object, in this example, the jsfacile.test.RecursionTest object):
scala> showRaw(fooType)
val res2: String = TypeRef(SingleType(SingleType(SingleType(ThisType(<root>), jsfacile), jsfacile.test), jsfacile.test.RecursionTest), jsfacile.test.RecursionTest.Foo, List(TypeRef(ThisType(scala), scala.Int, List())))
scala> showRaw(nextAppliedType)
val res3: String = TypeRef(ThisType(jsfacile.test.RecursionTest), jsfacile.test.RecursionTest.Foo, List(TypeRef(ThisType(scala), scala.Int, List())))
The reason I need this is difficult to explain. Let's try:
I am developing this JSON library which works fine except when there is a recursive type reference. For example:
sealed trait Foo[V]
case class FooImpl[V](next: Foo[V]) extends Foo[V]
That happens because the parser/appender it uses to parse and format are type classes that are materialized by an implicit macro. And when an implicit parameter is recursive the compiler complains with a divergence error.
I tried to solve that using by-name implicit parameter but it not only didn't solve the recursion problem, but also makes many non recursive algebraic data type to fail.
So, now I am trying to solve this problem by storing the resolved materializations in a map, which also would improve the compilation speed. And that map key is of type Type. So I need to normalize the Type instances, not only to be usable as key of a map, but also to equalize the values generated from them.
If I understood you well, any equivalence class would be fine. There is no preference.
I suspect you didn't. At least "any equivalence class would be fine", "There is no preference" do not sound good. I'll try to elaborate.
In math there is such construction as factorization. If you have a set A and equivalence relation ~ on this set (relation means that for any pair of elements from A we know whether they are related a1 ~ a2 or not, equivalence means symmetricity a1 ~ a2 => a2 ~ a1, reflexivity a ~ a, transitivity a1 ~ a2, a2 ~ a3 => a1 ~ a3) then you can consider the factor-set A/~ whose elements are all equivalence classes A/~ = { [a] | a ∈ A} (the equivalence class
[a] = {b ∈ A | b ~ a}
of an element a is a set consisting of all elements equivalent (i.e. ~-related) to a).
The axiom of choice says that there is a map (function) from A/~ to A i.e. we can select a representative in every equivalence class and in such way form a subset of A (this is true if we accept the axiom of choice, if we don't then it's not clear whether we get a set in such way). But even if we accept the axiom of choice and therefore there is a function A/~ -> A this doesn't mean we can construct such function.
Simple example. Let's consider the set of all real numbers R and the following equivalence relation: two real numbers are equivalent r1 ~ r2 if their difference is a rational number
r2 - r1 = p/q ∈ Q
(p, q≠0 are arbitrary integers). This is an equivalence relation. So it's known that there is a function selecting a single real number from any equivalence class but how to define this function explicitly for a specific input? For example what is the output of this function for the input being the equivalence class of 0 or 1 or π or e or √2 or log 2...?
Similarly, =:= is an equivalence relation on types, so it's known that there is a function normalize (maybe there are even many such functions) selecting a representative in every equivalence class but how to prefer a specific one (how to define or construct the output explicitly for any specific input)?
Regarding your struggle against implicit divergence. It's not necessary that you've selected the best possible approach. Sounds like you're doing some compiler work manually. How do other json libraries solve the issue? For example Circe? Besides by-name implicits => there is also shapeless.Lazy / shapeless.Strict (not equivalent to by-name implicits). If you have specific question about deriving type classes, overcoming implicit divergence maybe you should start a different question about that?
Regarding your approach with HashMap with Type keys. I'm still reminding that we're not supposed to rely on == for Types, correct comparison is =:=. So you should build your HashMap using =:= rather than ==. Search at SO for something like: hashmap custom equals.
Actually I guess your normalize sounds like you want some caching. You should have a type cache. Then if you asked to calculate normalize(typ) you should check whether in the cache there is already a t such that t =:= typ. If so you should return t, otherwise you should add typ to the cache and return typ.
This satisfies your requirement: A =:= B if and only if normalize(A) == normalize(B) (normalize(A).hashCode == normalize(B).hashCode should follow from normalize(A) == normalize(B)).
Regarding transformation of fooType into nextAppliedType try
def normalize(typ: Type): Type = typ match {
case TypeRef(pre, sym, args) =>
internal.typeRef(internal.thisType(pre.typeSymbol), sym, args)
}
Then normalize(fooType) == nextAppliedType should be true.

Scala equivalent of Java's Number with divide method

I want to generalise this function
def selfSufficiency(a: Seq[Double], b: Seq[Double]): Double =
a.sum/b.sum
I tried using the ideas provided here to implement a more general function that work with Doubles, Floats, Ints, etc.:
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Numeric[A]):A = {
import n._
a.sum/b.sum
}
I however get a remark from eclipse saying that
value / is not a member of type parameter A.
1- How can I implement this in functional/generalisable way?
2- Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
selfSufficiency(Seq(1,2,3), Seq(2.0,1.3))
if I cannot, please explain how to implement this?
Please note that the code here provide a toy example. In my production function, I add, subtract, find the larger number, etc.
The problem is that Numeric doesn't encode the division function - you need a Fractional.
Thus your code becomes
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Fractional[A]):A = {
import n._
a.sum/b.sum
}
And now it works.
Edit
I just read this part of your question.
Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
Because both Fractional and Numeric are parametrized in just one T, both arguments have to be from the same type - for example take a look to the div function.
However, since numeric values of less precision are subtypes of the ones with higher (fig 1). You can make it work by upcast, but you will need to help the compiler a little more.
selfSufficiency[Double](Seq(1,2,3), Seq(2.0,1.3)) // res1: Double = 1.8181818181818183
Note: Without specifying the type as Double, the compiler will yield the following error.
error: could not find implicit value for parameter n: Fractional[AnyVal]
fig 1
Reference: https://www.artima.com/pins1ed/scalas-hierarchy.html
What you are looking for is the Fractional trait which is a more narrow Numeric (subtype) that supports div.

how scala folding works?

I am trying to understand the following code but can't.
it is supposed to create a child actor for an Event if it does not exist, otherwise says that the Event exist as it as an associated child actor.
context.child(name).fold(create())(_ => sender() ! EventExists)
But the fold here does not make sense to me. If the context.child is emtpty we get the creation and i understand that. However if there is children we are still going to create why ?
Akka's child returns an Option
As you can see from Option's scaladoc:
fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B Returns the result of
applying f to this scala.Option's value if the scala.Option is
nonempty. Otherwise, evaluates expression ifEmpty.
Or making it more clear:
This (fold) is equivalent to scala.Option map f getOrElse ifEmpty.
So the first parameter of fold is lazy (call-by-name) and evaluates only if Option is empty. The second parameter (a function) is called only if Option is not empty.
Experiment:
scala> Some(0).fold({println("1");1}){_ => println("2"); 2}
2
res0: Int = 2
scala> None.fold({println("1");1}){_ => println("2"); 2}
1
res1: Int = 1
Here's some readings about:
https://kwangyulseo.com/2014/05/21/scala-option-fold-vs-option-mapgetorelse/
And some critics of that approach:
http://www.nurkiewicz.com/2014/06/optionfold-considered-unreadable.html
But in Option.fold() the contract is different: folding function takes
just one parameter rather than two. If you read my previous article
about folds you know that reducing function always takes two
parameters: current element and accumulated value (initial value
during first iteration). But Option.fold() takes just one parameter:
current Option value! This breaks the consistency, especially when
realizing Option.foldLeft() and Option.foldRight() have correct
contract (but it doesn't mean they are more readable).

Scala: reduceLeft with String

I have a list of Integers and I want to make a String of it.
var xs = list(1,2,3,4,5)
(xs foldLeft "") (_+_) // String = 12345
with foldLeft it works perfect, but my question is does it also work with reduceLeft? And if yes, how?
It cannot work this way with reduceLeft. Informally you can view reduceLeft as a special case of foldLeft where the accumulated value is of the same type as the collection's elements. Because in your case the element type is Int and the accumulated value is String, there is no way to use reduceLeft in the way you used foldLeft.
However in this specific case you can simply convert all your Int elements to String up front, and then reduce:
scala> xs.map(_.toString) reduceLeft(_+_)
res5: String = 12345
Note that this will throw an exception if the list is empty. This is another difference with foldLeft, which handles the empty case just fine (because it has an explicit starting value).
This is also less efficient because we create a whole new collection (of strings) just to reduce it on the spot.
All in all, foldLeft is a much better choice here.
It takes a little bit of work to make sure the types are understood correctly. Expanding them, though, you could use something like:
(xs reduceLeft ((a: Any, b: Int) => a + b.toString)).toString

Why does Scala warn about type erasure in the first case but not the second?

I have two functions (not these have been edited since the original -- some of the answers below are responding to the original ones which returned a sequence of ()):
def foo1[A](ls: Iterable[A]) : Iterator[A] =
for (List(a, b) <- ls sliding 2) yield a
def foo2[A](ls: Iterable[A]) : Iterator[A] =
for (a::b::Nil <- ls sliding 2) yield a
which I naively thought were the same. But Scala gives this waning only for the first one:
warning: non variable type-argument A in type pattern List[A]
is unchecked since it is eliminated by erasure
I think I understand why it gives that error for the first one: Scala thinks that I'm trying to use the type as a condition on the pattern, ie a match against List[B](_, _) should fail if B does not inherit from A, except that this can't happen because the type is erased in both cases.
So two questions:
1) Why does the second one not give the same warning?
2) Is it possible to convince Scala that the type is actually known at compile time, and thus can't possibly fail to match?
edit: I think this answers my first question. But I'm still curious about the second one.
edit: agilesteel mentioned in a comment that
for (List(a, b) <- List(1,2,3,4) sliding 2) yield ()
produces no warning. How is that different from foo1 (shouldn't the [Int] parameter be erased just the same as the [A] parameter is)?
I'm not sure what is happening here, but the static type of Iterable[A].sliding is Iterator[Iterable[A]], not Iterator[List[A]] which would be the static type of List[A].sliding.
You can try receiving Seq instead of Iterable, and that work too. EDIT Contrary to what I previously claimed, both Iterable and Seq are co-variant, so I don't know what's different. END EDIT The definition of sliding is pretty weird too:
def sliding [B >: A] (size: Int): Iterator[Iterable[A]]
See how it requires a B, superclass of A, that never gets used? Contrast that with an Iterator.sliding, for which there's no problem:
def sliding [B >: A] (size: Int, step: Int = 1): GroupedIterator[B]
Anyway, on to the second case:
for (a::b::Nil <- ls sliding 2) yield a
Here you are decomposing the list twice, and for each decomposition the type of head is checked against A. Since the type of head is not erased, you don't have a problem. This is also mostly a guess.
Finally, if you turn ls into a List, you won't have a problem. Short of that, I don't think there's anything you can do. Otherwise, you can also write this:
def foo1[A](ls: Iterable[A]) : Iterator[A] =
for (Seq(a, b) <- ls.iterator sliding 2) yield a
1) The second one does not produce a warning probably because you are constructing the list (or the pattern) by prepending elements to the Nil object, which extends List parameterising it with Nothing. And since everything is Nothing, there is nothing to be worried about ;) But I'm not sure, really guessing here.
2) Why don't you just use:
def foo[A](ls: Iterable[A]) =
for (list <- ls sliding 2) yield ()