I have updated IntelliJ Idea Ultimate and scala plugin, it's working ok so far with sbt to build some projects.
Using a scala worksheet in REPL Interactive mode, I put in some code from a course lecture,
val rand = java.util.Random()
trait Generator[+T]:
def generate(): T
def map[S](f: T => S) = new Generator[S]:
def generate() = f(Generator.this.generate())
def flatMap[S](f: T => Generator[S]) = new Generator[S]:
def generate() = f(Generator.this.generate()).generate()
val integers = new Generator[Int]:
def generate() = rand.nextInt()
val booleans = for x <- integers yield x > 0
def single[T](x: T): Generator[T] = new Generator[T]:
def generate() = x
def lists: Generator[List[Int]] =
for
isEmpty <- booleans
list <- if isEmpty then emptyLists else nonEmptyLists // *1
yield list
def emptyLists = single(Nil)
def nonEmptyLists =
for
head <- integers
tail <- lists // *2
yield head :: tail
At *1 I got
4 | list <- if isEmpty then emptyLists else nonEmptyLists
| ^^^^^^^^^^
| Not found: emptyLists
4 | list <- if isEmpty then emptyLists else nonEmptyLists
| ^^^^^^^^^^^^^
| Not found: nonEmptyLists
At *2 I got
4 | tail <- lists
| ^^^^^
| Not found: lists
Maybe some tweak to the settings I haven't found yet?
Put everything in an object.
This way the 2 defs that depends on each other will be available at the same time.
IntelliJ worksheets do not like such definitions as they are "evaluated" one by one. You cannot define 2 depending on one the other at the top-level, they need to be encapsulated.
Related
I've got a coding draft which works so far as it delivers the correct answer. But from the esthetics side, it could be improved, my guess!
Aim: Find first solution in a list of many possible solutions. When found first solution, don't calculate further. In real-world application, the calculation of each solution/non-solution might be more complex for sure.
Don't like: The Solution=Left and NoSolution=Right aliasing is contra-intuitive, since Right normally stands for success and here Left and Right are swapped (since technically when using Either only Left shortcuts the for-comprehension list)
Is there a nice way to improve this implementation? or another solution?
package playground
object Test {
def main(args: Array[String]): Unit = {
test
}
val Solution = Left
val NoSolution = Right
def test: Unit = {
{
// Find the first solution in a list of computations and print it out
val result = for {
_ <- if (1 == 2) Solution("impossible") else NoSolution()
_ <- NoSolution()
_ <- NoSolution(3)
_ <- Solution("*** Solution 1 ***")
_ <- NoSolution("oh no")
_ <- Solution("*** Solution 2 ***")
x <- NoSolution("no, no")
} yield x
if (result.isLeft)
println(result.merge) // Prints: *** Solution 1 ***
}
}
}
So you're looking for something that's "monaduck": i.e. has flatMap/map but doesn't necessarily obey any monadic laws (Scala doesn't even require that flatMap have monadic shape: the chain after desugaring just has to typecheck); cf. duck-typing.
trait Trial[+Result] {
def result: Option[Result]
def flatMap[R >: Result](f: Unit => Trial[R]): Trial[R]
def map[R](f: Result => R): Trial[R]
}
case object NoSolution extends Trial[Nothing] {
def result = None
def flatMap[R](f: Unit => Trial[R]): Trial[R] = f(())
def map[R](f: Result => R): Trial[R] = this
}
case class Solution[Result](value: Result) extends Trial[Result] {
def result = Some(value)
def flatMap[R >: Result](f: Unit => Trial[R]): Trial[R] = this
def map[R](f: Result => R): Trial[R] = Solution(f(value))
}
scala> for {
| _ <- if (1 == 2) Solution("nope") else NoSolution
| _ <- NoSolution
| _ <- Solution("yay!")
| _ <- NoSolution
| x <- Solution("nope")
| } yield x
res0: Trial[String] = Solution(yay!)
scala> for {
| _ <- if (1 == 2) Solution("nope") else NoSolution
| _ <- NoSolution
| _ <- Solution("yay!")
| x <- NoSolution
| } yield x
res1: Trial[String] = Solution(yay!)
scala> for {
| _ <- if (1 == 2) Solution("nope") else NoSolution
| x <- NoSolution
| } yield x
res2: Trial[String] = NoSolution
Clearly, monadic laws are being violated: the only thing we could use for pure is Solution, but
scala> val f: Unit => Trial[Any] = { _ => NoSolution }
f: Unit => Trial[Any] = $Lambda$107382/0x00000008433be840#6c0e35d7
scala> Solution(5).flatMap(f)
res7: Trial[Any] = Solution(5)
scala> f(5)
<console>:13: warning: a pure expression does nothing in statement position
f(5)
^
res8: Trial[Any] = NoSolution
Absent Scala's willingness to convert any pure value to Unit, that wouldn't even type check, but still, it breaks left identity.
Given:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def f: Future[Either[String, Int]] = Future { Right(100)}
def plus10(x: Int): Future[Either[String, Int]] =
Future { Right(x + 10) }
I'm trying to chain the Future[...] together as so:
scala> for {
| x <- f
| y <- for { a <- x.right } yield plus10(a)
| } yield y
<console>:17: error: value map is not a member of Product with
Serializable with
scala.util.Either[String,scala.concurrent.Future[Either[String,Int]]]
y <- for { a <- x.right } yield plus10(a)
^
I am expecting to get: Future{Right(100)} as a result, but I get the above compile-time error.
Travis Brown gave an excellent answer on how to use Monad Transformers to fix my code here. However, how can I fix my code without Monad Transformers?
Turns out that I can use Either#fold:
scala> for {
| a <- f
| b <- a.fold(_ => Future { Left("bad") }, xx => plus10(xx) )
| } yield b
res16: scala.concurrent.Future[Either[String,Int]] =
scala.concurrent.impl.Promise$DefaultPromise#67fc2aad
scala> res16.value
res17: Option[scala.util.Try[Either[String,Int]]] =
Some(Success(Right(110)))
I was about to answer when yours appeared, but you might still look at this:
val res = for {
x <- f
y <- x.fold(x => Future{Left(x)}, plus10)
} yield y
It is a little more concise on the right side and keeps the left side.
According to this answer https://stackoverflow.com/a/8001065/1586965 we can do this in Scala:
val _ = 5
Now I understand the point of ignored parameters in lambda expressions, but I cannot really imagine examples where I would ever want to declare a variable that by definition I cannot reference. The only example I can think of is being lazy about naming implicit values, e.g.
implicit val _: MyNumeric = ...
...
class A[T : MyNumeric] {
...
Is this the only use case? Am I missing something?
If it is the only use case, shouldn't the compiler/IDE give a warning/hint when the val is not implicit as it is utterly pointless?
Clarification
By variable/value I mean a single one, not one that is part of an extraction declaration.
I don't think that this is a feature at all. In any case, it is not an "ignored variable".
By which I mean that if val _ = 5 really introduced an unnamed value, then you could declare as many as you want in the same single scope.
Not so:
scala> object Test {
| val _ = 5
| val _ = 7
| }
<console>:9: error: _ is already defined as value _
val _ = 7
^
From the error message it seems clear that what really happens is that the value is actually named _
(which I'd call a quirk of the compiler that should be fixed). We can verify this:
scala> object Test {
| val _ = 5
| def test() { println( `_` ) } // This compiles fine
| }
defined object Test
scala> Test.test()
5
As for the possible use of preventing a value discarding warning (as shown in som-snytt's answer), I'much prefer to simply return an explicit Unit.
This looks less convoluted and is even shorter:
def g(): Unit = { f(); () }
as opposed to:
def g(): Unit = { val _ = f() }
It uses a value.
$ scala -Ywarn-value-discard
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def f() = { println("I ran.") ; 42 }
f: ()Int
scala> def g(): Unit = { f() }
<console>:8: warning: discarded non-Unit value
def g(): Unit = { f() }
^
g: ()Unit
scala> def g(): Unit = { val _ = f() }
g: ()Unit
scala> g
I ran.
scala>
To verify, it also doesn't warn under -Ywarn-unused.
The other use case (that I can think of) is related to extraction (and is called out under "Wildcard patterns" in the linked answer):
val getCartesianPoint = () => (1, 2, 3)
// We don't care about the z axis, so we assign it to _
val (x, y, _) = getCartesianPoint()
val regex = "(.*?)|(.*?)|?.*".r
// Really, any unapply or unapplySeq example will do
val regex(_, secondValue) = "some|delimited|value|set"
As I understand it, Scala "for" syntax is extremely similar to Haskell's monadic "do" syntax. In Scala, "for" syntax is often used for Lists and Options. I'd like to use it with Eithers, but the necessary methods are not present in the default imports.
for {
foo <- Right(1)
bar <- Left("nope")
} yield (foo + bar)
// expected result: Left("nope")
// instead I get "error: value flatMap is not a member..."
Is this functionality available through some import?
There is a slight hitch:
for {
foo <- Right(1)
if foo > 3
} yield foo
// expected result: Left(???)
For a List, it would be List(). For Option, it would be None. Do the Scala standard libraries provide a solution to this? (Or perhaps scalaz?) How? Suppose I wanted to provide my own "monad instance" for Either, how could I do that?
It doesn't work in scala 2.11 and earlier because Either is not a monad. Though there's talk of right-biasing it, you can't use it in a for-comprehension: you have to get a LeftProject or RightProjection, like below:
for {
foo <- Right[String,Int](1).right
bar <- Left[String,Int]("nope").right
} yield (foo + bar)
That returns Left("nope"), by the way.
On Scalaz, you'd replace Either with Validation. Fun fact: Either's original author is Tony Morris, one of Scalaz authors. He wanted to make Either right-biased, but was convinced otherwise by a colleague.
Is this functionality available through some import?
Yes, but via a third party import: Scalaz provides a Monad instance for Either.
import scalaz._, Scalaz._
scala> for {
| foo <- 1.right[String]
| bar <- "nope".left[Int]
| } yield (foo.toString + bar)
res39: Either[String,java.lang.String] = Left(nope)
Now if-guard is not a monadic operation. Therefore if you attempt to use if-guard, it results in a compiler error as expected.
scala> for {
| foo <- 1.right[String]
| if foo > 3
| } yield foo
<console>:18: error: value withFilter is not a member of Either[String,Int]
foo <- 1.right[String]
^
The convenience methods used above - .right and .left - are also from Scalaz.
Edit:
I missed this question of yours.
Suppose I wanted to provide my own "monad instance" for Either, how could I do that?
Scala for comprehensions are simply translated to .map, .flatMap, .withFilter, and .filter .foreach calls on the objects involved. (You can find the the full translation scheme here.) So if some class does not have the required methods, you can add them to a class using implicit conversions.
A fresh REPL session below.
scala> implicit def eitherW[A, B](e: Either[A, B]) = new {
| def map[B1](f: B => B1) = e.right map f
| def flatMap[B1](f: B => Either[A, B1]) = e.right flatMap f
| }
eitherW: [A, B](e: Either[A,B])java.lang.Object{def map[B1](f: B => B1): Product
with Either[A,B1] with Serializable; def flatMap[B1](f: B => Either[A,B1]):
Either[A,B1]}
scala> for {
| foo <- Right(1): Either[String, Int]
| bar <- Left("nope") : Either[String, Int]
| } yield (foo.toString + bar)
res0: Either[String,java.lang.String] = Left(nope)
As of Scala 2.12, Either is now right biased
From the documentation:
As Either defines the methods map and flatMap, it can also be used in for comprehensions:
val right1: Right[Double, Int] = Right(1)
val right2 = Right(2)
val right3 = Right(3)
val left23: Left[Double, Int] = Left(23.0)
val left42 = Left(42.0)
for (
a <- right1;
b <- right2;
c <- right3
) yield a + b + c // Right(6)
for (
a <- right1;
b <- right2;
c <- left23
) yield a + b + c // Left(23.0)
for (
a <- right1;
b <- left23;
c <- right2
) yield a + b + c // Left(23.0)
// It is advisable to provide the type of the “missing” value (especially the right value for `Left`)
// as otherwise that type might be infered as `Nothing` without context:
for (
a <- left23;
b <- right1;
c <- left42 // type at this position: Either[Double, Nothing]
) yield a + b + c
// ^
// error: ambiguous reference to overloaded definition,
// both method + in class Int of type (x: Char)Int
// and method + in class Int of type (x: Byte)Int
// match argument types (Nothing)
I find myself using a lot of nested maps, e.g a Map[Int, Map[String, Set[String]]], and I'd like to have new Maps, Sets, etc. created automatically when I access a new key. E.g. something like the following:
val m = ...
m(1992)("foo") += "bar"
Note that I don't want to use getOrElseUpdate here if I don't have to because it gets pretty verbose when you have nested maps and obscures what's actually going on in the code:
m.getOrElseUpdate(1992, Map[String, Set[String]]()).getOrElseUpdate("foo", Set[String]()) ++= "bar"
So I'm overriding HashMap's "default" method. I've tried two ways of doing this, but neither is fully satisfactory. My first solution was to write a method that created the map, but it seems that I still have to specify the full nested Map type when I declare the variable or things don't work:
scala> def defaultingMap[K, V](defaultValue: => V): Map[K, V] = new HashMap[K, V] { | override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
defaultingMap: [K,V](defaultValue: => V)scala.collection.mutable.Map[K,V]
scala> val m: Map[Int, Map[String, Set[String]]] = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Int,scala.collection.mutable.Map[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
scala> val m = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Nothing,scala.collection.mutable.Map[Nothing,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
<console>:11: error: type mismatch;
found : Int(1992)
required: Nothing
m(1992)("foo") += "bar"; println(m)
^
My second solution was to write a factory class with a method, and that way I only have to declare each type a single time. But then each time I want a new default valued map, I have to both instantiate the factory class and then call the method, which still seems a little verbose:
scala> class Factory[K] {
| def create[V](defaultValue: => V) = new HashMap[K, V] {
| override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
| }
defined class Factory
scala> val m = new Factory[Int].create(new Factory[String].create(Set[String]()))
m: scala.collection.mutable.HashMap[Int,scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
I'd really like to have something as simple as this:
val m = defaultingMap[Int](defaultingMap[String](Set[String]()))
Anyone see a way to do that?
With Scala 2.8:
object DefaultingMap {
import collection.mutable
class defaultingMap[K] {
def apply[V](v: V): mutable.Map[K,V] = new mutable.HashMap[K,V] {
override def default(k: K): V = {
this(k) = v
v
}
}
}
object defaultingMap {
def apply[K] = new defaultingMap[K]
}
def main(args: Array[String]) {
val d4 = defaultingMap[Int](4)
assert(d4(3) == 4)
val m = defaultingMap[Int](defaultingMap[String](Set[String]()))
m(1992)("foo") += "bar"
println(m)
}
}
You can't curry type parameters in Scala, therefore the trick with the class to capture the key type is necessary.
By the way: I don't think that the resulting API is very clear. I particularly dislike the side-effecting map access.
Turns out I need to extend MapLike as well, or when I call filter, map, etc. my default valued map will get turned back into a regular Map without the defaulting semantics. Here's a variant of mkneissl's solution that does the right thing for filter, map, etc.
import scala.collection.mutable.{MapLike,Map,HashMap}
class DefaultingMap[K, V](defaultValue: => V) extends HashMap[K, V]
with MapLike[K, V, DefaultingMap[K, V]] {
override def empty = new DefaultingMap[K, V](defaultValue)
override def default(key: K): V = {
val result = this.defaultValue
this(key) = result
result
}
}
object DefaultingMap {
def apply[K] = new Factory[K]
class Factory[K] {
def apply[V](defaultValue: => V) = new DefaultingMap[K, V](defaultValue)
}
}
And here that is, in action, doing the right thing with filter:
scala> val m = DefaultingMap[String](0)
m: DefaultingMap[String,Int] = Map()
scala> for (s <- "the big black bug bit the big black bear".split(" ")) m(s) += 1
scala> val m2 = m.filter{case (_, count) => count > 1}
m2: DefaultingMap[String,Int] = Map((the,2), (big,2), (black,2))