What does not compile? - scala

I have a trait as follow:
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
}
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
When I try to compile I've got following error:
scala> :load "src/Option.scala"
Loading src/Option.scala...
src/Option.scala:17: error: pattern type is incompatible with expected type;
found : None.type
required: Option[A]
case None => None
^
src/Option.scala:17: error: type mismatch;
found : None.type
required: Option[B]
case None => None
^
src/Option.scala:18: error: constructor cannot be instantiated to expected type;
found : Some[A(in class Some)]
required: Option[A(in trait Option)]
case Some(a) => Some(f(a))
^
src/Option.scala:18: error: type mismatch;
found : Some[B]
required: Option[B]
case Some(a) => Some(f(a))
^
src/Option.scala:11: error: illegal inheritance from sealed class Option
case class Some[+A](get: A) extends Option[A]
^
src/Option.scala:11: error: illegal inheritance from sealed class Option
case object None extends Option[Nothing]
Why?
I am new in scala world and can not differ if the map is function or a method? How can I use map?

Related

Scala compilation error: not found: type _$1

I am researching about existential types in Scala 2.12.x. For that I'm testing the following code:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[_ <: ChildA] => "ChildA"
case _: Option[_ <: ChildB] => "ChildB"
case _ => throw new IllegalArgumentException("unknown type")
}
}
whatIsInside(Some(new ChildA))
I don't expect this to work at runtime because of type erasure, but nevertheless this does not even compile. I am getting the following error:
[error] ExistentialTypes.scala:12:24: not found: type _$2
[error] case _: Option[_ <: ChildA] => "ChildA"
[error] ^
[error] ExistentialTypes.scala:13:24: not found: type _$3
[error] case _: Option[_ <: ChildB] => "ChildB"
[error] ^
Can someone explain these errors?
(Not a full answer, but a few notes and links; Maybe it can serve as a starting point for someone else)
In 2.12.13, the compiler seems to be able to prove that F[_ <: X] and F[X] are the same type if X occurs in covariant position:
println(implicitly[Option[_ <: ChildA] =:= Option[ChildA]])
This compiles (with warnings, but it compiles):
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[ChildA] => "ChildA"
case _: Option[ChildB] => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
This does not compile:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[_ <: Parent]): String = {
opt match {
case _: Option[_ <: ChildA] => "ChildA"
case _: Option[_ <: ChildB] => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
So, it seems that it must have something to do with the bounds inference for the synthetic _$2 type-variable.
Also, this compiles:
def testConforms[A >: Nothing <: ChildA](ca: Option[A]): Option[_ <: Parent] = ca
so, unless I'm misinterpreting the spec:
If there exists a substitution σ over the type variables a_i,…,a_n such that σT conforms to pt, one determines the weakest subtype constraints C1 over the type variables a1,…,an such that C0 ∧ C1 implies that T conforms to [the expected type] pt.
, the pt would be Option[_ <: Parent], then a1,...,an would be the single synthetic type _$2, and the constraints _$2 >: Nothing <: ChildA should make the type Option[_$2] conform to Option[_ <: Parent]. So, it seems that it should work, but doesn't.
Bonus
If you just wanted to make it work, then just skip all those wildcards, they aren't needed:
trait Parent
class ChildA extends Parent
class ChildB extends Parent
def whatIsInside(opt: Option[Parent]): String = {
opt match {
case Some(_: ChildA) => "ChildA"
case Some(_: ChildB) => "ChildB"
case None => "None"
case _ => throw new Error("meh")
}
}
whatIsInside(Some(new ChildA))
whatIsInside(Some(new ChildB))
whatIsInside(None)

Returning subclass of parameterized type in Scala

I'm trying to return a subclass of a parameterized type Output[T <: Input] but for some reason I cannot seem to get the syntax right:
sealed trait Input
case class A(id: Int) extends Input
case class B(id: String) extends Input
sealed trait Output[+T <: Input]
case class OutA(some: String) extends Output[A]
case class OutB(thing: Int) extends Output[B]
def doStuff[T <: Input, RT <: Output[T]](input: T): RT =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: RT
// case A(i) => OutA(i.toString)
//
// error: type mismatch;
// found : OutB
// required: RT
// case B(s) => OutB(s.toInt)
def doStuff[T <: Input](input: T): Output[T] =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: Output[T]
// case A(i) => OutA(i.toString)
// error: type mismatch;
// found : OutB
// required: Output[T]
// case B(s) => OutB(s.toInt)
def doStuff[T <: Input, RT <: Output[_]](input: T): RT =
input match {
case A(i) => OutA(i.toString)
case B(s) => OutB(s.toInt)
}
// error: type mismatch;
// found : OutA
// required: RT
// case A(i) => OutA(i.toString)
// error: type mismatch;
// found : OutB
// required: RT
// case B(s) => OutB(s.toInt)
In my actual code the Input and Output subclasses are wrapped in containers that I cannot modify and the input is also coming from another system over which I have no control. However, this seems to be the smallest example I could come up with for which I get the same compile-time type errors.
How can I solve my problem?
You can do it this way (this is an example of a type class in Scala, searching for this term will give you quite a few posts explaining the pattern):
case class StuffDoer[T](doStuff: T => Output[T])
object StuffDoer {
implicit val ADoer: StuffDoer[A] = StuffDoer(x => OutA(x.id.toString))
implicit val BDoer: StuffDoer[B] = StuffDoer(x => OutB(x.id.toInt))
implicit val InputDoer: StuffDoer[Input] = StuffDoer {
case a: A => ADoer.doStuff(a)
case b: B => BDoer.doStuff(b)
}
}
def doStuff[T](input: T)(implicit doer: StuffDoer[T]) = doer.doStuff(input)
(Really, some variation of this problem is asked from time to time, but writing the answer is faster than searching for previous questions.)

Scala subclass pattern match

I'm trying to run code from the book "Functional Programming in Scala" which seems to be made for an older version of scala (download from here). tmp.scala:
sealed trait Option[+A]
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
trait Option[+A] {
/* returns None if None, or function applied to the some object */
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
}
The errors this throws are:
$ scala
Welcome to Scala 2.12.0-20161021-070700-8684ae8 (OpenJDK 64-Bit Server VM, Java 1.8.0_112).
scala> :load tmp.scala
tmp.scala:17: error: pattern type is incompatible with expected type;
found : None.type
required: Option[A]
case None => None
^
tmp.scala:17: error: type mismatch;
found : None.type
required: Option[B]
case None => None
^
tmp.scala:18: error: constructor cannot be instantiated to expected type;
found : Some[A(in class Some)]
required: Option[A(in trait Option)]
case Some(a) => Some(f(a))
^
tmp.scala:18: error: type mismatch;
found : Some[B]
required: Option[B]
case Some(a) => Some(f(a))
^
I tried all sorts of codefu on this, but to no avail, it seems like it's not detecting the subclasses properly due to outdated syntax?
Use :paste file.scala, which pastes the content, instead of :load file.scala, which interprets each line.

scala pattern matching in trait

sealed trait Option_40to49[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(x) => Some(f(x))
}
}
I work in eclipse, it underlined None with the next error:
pattern type is incompatible with expected type; found : None.type required: packageName.Option_40to49[A]
and the similar with Some(x)
constructor cannot be instantiated to expected type; found : Some[A(in class Some)] required: packageName.Option_40to49[A(in trait Option_40to49)]
Why I have this problem? How to fix it?
By using this in your pattern match you're referring to your Option_40to49, but since you haven't implemented None or Some the compiler doesn't know what these are
Simple versions of these aren't that hard to implement yourself. Note, you'll also want to change your output for map to Option_40to49
sealed trait Option_40to49[+A] {
def map[B](f: A => B): Option_40to49[B] = this match {
case None => None
case Some(x) => Some(f(x))
}
}
case class Some[A](x: A) extends Option_40to49[A]
case object None extends Option_40to49[Nothing]

Implementing map on Option

Working more on FP in Scala examples, I tried to implement the Option trait's map function as follows:
sealed trait MyOption[+A] {
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case _ => None
}
}
However, compile-time errors show, if I understand correctly, that I'm not pattern-matching correctly for the case of Some(A). Using pattern matching, how can I write the first case to get Some(A) values to match?
>scalac MyOption.scala
MyOption.scala:3: error: constructor cannot be instantiated to expected type;
found : Some[A(in class Some)]
required: MyOption[A(in trait MyOption)]
case Some(a) => Some(f(a))
^
MyOption.scala:3: error: not found: value a
case Some(a) => Some(f(a))
^
two errors found
You are trying to define map in terms of Some and None which are subclasses of the Scala-provided Option trait, rather than in terms of subclasses of your own trait. Try something like:
sealed trait MyOption[+A] {
import MyOption._
def map[B](f: A => B): MyOption[B] = this match {
case MySome(a) => MySome(f(a))
case _ => MyNone
}
}
object MyOption {
case class MySome[+A](a: A) extends MyOption[A]
case object MyNone extends MyOption[Nothing]
}