I am using scalaz7 in a project and sometimes I run into issues with imports. The simplest way get started is
import scalaz._
import Scalaz._
but sometimes this can lead to conflicts. What I have been doing until now the following slightly painful process:
work out a minimal example that needs the same imports as my actual code
copy that example in a separate project
compile it with the option -Xprint:typer to find out how the code looks after implicit resolution
import the needed implicits in the original project.
Although this works, I would like to streamline it. I see that scalaz7 has much more fine-grained imports, but I do not fully understand how they are organized. For instance, I see one can do
import scalaz.std.option._
import scalaz.std.AllInstances._
import scalaz.std.AllFunctions._
import scalaz.syntax.monad._
import scalaz.syntax.all._
import scalaz.syntax.std.boolean._
import scalaz.syntax.std.all._
and so on.
How are these sub-imports organized?
As an example, say I want to work with validations. What would I need, for instance to inject validation implicits and make the following compile?
3.fail[String]
What about making ValidationNEL[A, B] an instance of Applicative?
This blog post explains the package structure and imports a la carte in scalaz7 in detail: http://eed3si9n.com/learning-scalaz-day13
For your specific examples, for 3.failure[String] you'd need:
import scalaz.syntax.validation._
Validation already has a method ap:
scala> "hello".successNel[Int] ap ((s: String) => "x"+s).successNel[Int]
res1: scalaz.Validation[scalaz.NonEmptyList[Int],java.lang.String] = Success(xhello)
To get the <*> operator, you need this import:
import scalaz.syntax.applicative._
Then you can do:
"hello".successNel[Int] <*> ((s: String) => "x"+s).successNel[Int]
Related
why the second folding compile error ?
I think the first folding and the second one are completely same.
But the second one arise compile error.
import cats._
import cats.data._
import cats.syntax.all._
val somes : List[Option[Int]] = List(Some(1), Some(2))
Foldable[List].fold(somes)
Foldable[List].fold(List(Some(1), Some(2)))
compile error message is
No given instance of type cats.kernel.Monoid[Some[Int]] was found for parameter A of method fold in trait Foldable
I expect the code is compiled.
Doc tells that you need to import implicits as well
import cats.implicits._
here is the answer regarding Some and Option
I have a simple test setup like
package unit
import net.kolotyluk.leaderboard.scorekeeping._
import net.kolotyluk.leaderboard.telemetry.Metrics
import net.kolotyluk.scala.extras.Logging
import org.scalatest.{FlatSpec, GivenWhenThen, Matchers, SequentialNestedSuiteExecution}
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.{Await,Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Random, Success}
class LeaderboardSpec
extends FlatSpec
with SequentialNestedSuiteExecution
with GivenWhenThen
with Matchers
with Logging {
behavior of "Leaderboard"
it must "handle initial conditions correctly" in {
but when I try to compile my tests I get 53 errors like
[IJ]sbt:leaderboard> test
[info] Compiling 1 Scala source to C:\Users\ERIC\Documents\git\repos\leaderboard\target\scala-2.12\test-classes ...
[error] C:\Users\ERIC\Documents\git\repos\leaderboard\src\test\scala\unit\LeaderboardSpec.scala:21:12: could not find implicit value for parameter pos: org.scalactic.source.Position
[error] behavior of "Leaderboard"
[error] ^
Which does not actually convey any useful information on what the problem is. I can only assume that something is not configured correctly, either in my build.sbt file, or somewhere else.
This code did work at one time, and somewhere along the way I was cleaning things up, things changed, and now it's broken with no good diagnostics.
Can anyone suggest things to look for?
So one workaround that seems to compile and run correctly is to stop using SBT and use Maven instead.
I think this is the third major defect I have found in SBT so far.
I am learning Scala here https://scastie.scala-lang.org/iRJ8VOw7TySZ4KQ5qlWkdw.
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.SortedSet
// import scala.collection.immutable.Map // import not required to use immutable.Map
val m = Map((1 -> "a"), (2 -> "bb"))
val r = m.filter(_._1 > 1)
r // Map(2 -> bb): scala.collection.immutable.Map
println(r)
In the above codes, r is of type scala.collection.immutable.Map, even if scala.collection.immutable.Map not imported but scala.collection.mutable imported.
if import scala.collection.immutable.Map and scala.collection.mutable._, r is immutable.Map. if import scala.collection.mutable._, r is mutable.Map.
I am a little confused. Anyone can help explain it? Thanks
The first problem is that Map is not imported from scale.collection.mutable because there is a problem with your import statement.
Change
import scala.collection.mutable
to
import scala.collection.mutable._
or
import scala.collection.mutable.Map
and Map will be mutable.Map.
When you import both scale.collection.immutable.Map and scala.collection.mutable._ the immutable Map wins because it is a more specific. So the most specific import wins and in the case of a tie you will get a compiler error.
There are like five different questions in here, let's deal with them one by one.
Why import collection.mutable seemingly does nothing?
If we omit the unnecessary details from your code snippet, we obtain:
import scala.collection.mutable
val r = Map(2 -> 3)
You asked why r is still scala.collection.immutable.Map.
First, notice that
import scala.collection.mutable
is not the same as
import scala.collection.mutable._
The latter is a wildcard import (which would import mutable Map on demand), whereas the former only imports the symbol mutable. Therefore, in your code, only the symbol mutable is made available, but this does not influence the meaning of Map in any way.
Where does the scala.collection.immutable.Map come from even if nothing is imported?
The Predef is always imported implicitly (unless you deactivate it with a compiler flag). There is a type alias definition
type Map[A, +B] = collection.immutable.Map[A, B]
in Predef, and there is also the direct shortcut to the companion object of immutable.Map:
val Map: collection.immutable.Map.type
which allows you to construct maps using the Map(...)-syntax without new-keyword.
Why does import collection.immutable.Map take precedence over import collection.mutable._?
The specification states about the precedence of imports:
Definitions and declarations that are local, inherited, or made available by a package clause in the same compilation unit where the definition occurs have highest precedence.
Explicit imports have next highest precedence.
Wildcard imports have next highest precedence.
Definitions made available by a package clause not in the compilation unit where the definition occurs have lowest precedence.
Therefore, because of points 2 and 3, an explicit import
import scala.collection.mutable.Map
has precedence over the wildcard import
import scala.collection.immutable._
Why import collection.mutable._ makes Map mutable?
Now, one last thing is left to clarify: why does the mutable._ wildcard import take precedence over the definition in Predef? Here is a short example that demonstrates it:
import scala.collection.mutable._
val m = Map()
println(m.getClass)
The output is (maybe somewhat surprisingly):
class scala.collection.mutable.HashMap
The specification seems to be a bit vague on this point, at least I could not find where it says that ordinary wildcard imports overshadow the definitions in Predef. However, here it says:
Every compilation unit implicitly imports the following packages, in the given order:
the package java.lang,
the package scala, and
the object scala.Predef, unless there is an explicit top-level import that references scala.Predef.
Members of a later import in that order hide members of an earlier import.
I think the last sentence also covers the imports that come after scala.Predef that is, also the explicit wildcard imports. This is probably why import scala.collection.mutable._ overshadows the definitions in Predef.
What's going on in the REPL?
When you are experimenting with imports, you must keep in mind that the REPL evaluates every line as if it were in a new nested block. This means that, for example, the script
import scala.collection.mutable._
import scala.collection.immutable._
Map()
will result in
error: reference to Map is ambiguous
But if you type the same lines in a REPL one by one, then no error will occur, and you will get an immutable Map. This is because in the REPL, the above lines are interpreted as
import scala.collection.mutable._
{
import scala.collection.immutable._
{
Map()
}
}
so that the last import takes precedence. I'm not sure how Scastie handles it, probably it's the same there, so it is one additional complication that you have to keep in mind.
By default a Map in Scala is immutable.
You donĀ“t import mutable.Map, so it is still immutable.
If you import it like this it should work:
import scala.collection.mutable.Map
if import scala.collection.immutable.Map and
scala.collection.mutable., r is immutable.Map. if import
scala.collection.mutable., r is mutable.Map.
The most qualified import statement wins.
By default Scala gives us immutable Map. There are two ways to create mutable Map:
**1.** Use import statement - *scala.collection.mutable._* to bring mutable map it into scope
**2.** Specify the full path to *scala.collection.mutable.Map*
With the import "import scala.collection.mutable._", you are importing the all the mutable collection available along with mutable map.
If you are adding scala.collection.immutable.Map along with scala.collection.mutable._, you are telling the scala compiler to use all mutable collection, but in case of Map, use immutable.
tl;dr use import scala.collection.mutable.Map
This is because m is an instance of scala.collection.immutable.Map (the default behavior). Similar behavior in java everything in java.lang package is implicitly imported.
You imported the package immutable, this does not automatically bring into scope scala.collection.immutable.Map to hide scala.collection.mutable.Map
For this you should import scala.collection.mutable.Map
import scala.collection.mutable
val m = Map((1 -> "a"), (2 -> "bb"))
println(m.getClass) // class scala.collection.immutable.Map$Map2
val mutableMap = mutable.Map((1->"A"), (2->"BB"))
println(mutableMap.getClass) // class scala.collection.mutable.HashMap
Alternatively
import scala.collection.mutable.Map
val m = Map((1 -> "a"), (2 -> "bb"))
println(m.getClass) // class scala.collection.mutable.HashMap
I have this code which compiles and works fine
import cats.implicits._
Cartesian[ValidResponse].product(
getName(map).toValidated,
readAge(map).toValidated
).map(User.tupled)
However I don't like the import of cats.implicits._ because there is just too many classes there. I tried importing specific things related to Cartesians like
import cats.implicits.catsSyntaxCartesian
import cats.implicits.catsSyntaxUCartesian
import cats.implicits.catsSyntaxTuple2Cartesian
But these did not work. As a newbie I find the implicit imports very confusing because there are simply 1000s of them and the names are not very obvious. My only alternative is to import the entire universe by import cats.implicits._ and stop thinking about it.
In fact I have a broader confusion about cats.implicits, cats.instances._ and cats.syntax._. So far I am just importing these via trial and error. I am not really sure of when to import what.
Do not try to pick out specific things from cats.implicits. You either import the entire thing, or you don't use it at all. Further, there's no reason to be afraid of importing it all. It can't interfere with anything.
Ok, I lied. It will interfere if you import cats.instances.<x>._ and/or cats.syntax.<x>._ alongside cats.implicits._. These groups are meant to be mutually exclusive: you either import everything and forget about it with cats.implicits._, or you specifically select what you want to import with cats.instances and cats.syntax.
These two packages are not meant to be imported completely like cats.implicits. Instead, they include a bunch of objects. Each object contains some implicit instances/syntax, and you are meant to import from those.
import cats.implicits._ // Good, nothing to fear
// RESET IMPORTS
import cats.implicits.catsSyntaxCartesian // Bad, don't pick and choose
// RESET IMPORTS
import cats.instances._ // Bad, is useless
import cats.syntax._ // Ditto
// RESET IMPORTS
import cats.instances.list._ // ok
import cats.syntax.cartesian._ // ok
// RESET IMPORTS
import cats.implicits._
import cats.syntax.monad._ // Bad, don't mix these two
Additionally each of cats.{ instances, syntax } contains an all object, with the obvious function. The import cats.implicits._ is really a shortcut for import cats.syntax.all._, cats.instances.all._.
I'll start by saying that import cats.implicits._ is safe, reasonable and the recommended approach when starting. So if the only reason for this question is that you don't like importing too many classes, then I think you should just bite the bulled at leave that as is.
Additionally, I recommend you take a look at the official cats import guide. It tries to explain the package/logical structure of cats code and might make it easier to understand.
The "cats" library is organized in several "areas" that can be easily distinguished by their package name:
cats._ - This is where most of the typeclasses live (e.g. Monad, Foldable etc.)
cats.data._ - This is the home of data structures like Validated and State.
cats.instances._ - This is where the instances for the typeclasses defined in 1 are. For example if you import cats.instances.list._ you'll bring into scope the Show, Monad etc. instances for the standard List. This is what you're most likely interested in.
cats.syntax._ - has some syntax enrichment that makes code easier to write and read.
An example of ussing cats.syntax._ would be:
import cats.Applicative
import cats.syntax.applicative._
val listOfInt = 5.pure[List]
//instead of
val otherList = Applicative[List[Int]].pure(5)
I am using scalaz7 in a project and sometimes I run into issues with imports. The simplest way get started is
import scalaz._
import Scalaz._
but sometimes this can lead to conflicts. What I have been doing until now the following slightly painful process:
work out a minimal example that needs the same imports as my actual code
copy that example in a separate project
compile it with the option -Xprint:typer to find out how the code looks after implicit resolution
import the needed implicits in the original project.
Although this works, I would like to streamline it. I see that scalaz7 has much more fine-grained imports, but I do not fully understand how they are organized. For instance, I see one can do
import scalaz.std.option._
import scalaz.std.AllInstances._
import scalaz.std.AllFunctions._
import scalaz.syntax.monad._
import scalaz.syntax.all._
import scalaz.syntax.std.boolean._
import scalaz.syntax.std.all._
and so on.
How are these sub-imports organized?
As an example, say I want to work with validations. What would I need, for instance to inject validation implicits and make the following compile?
3.fail[String]
What about making ValidationNEL[A, B] an instance of Applicative?
This blog post explains the package structure and imports a la carte in scalaz7 in detail: http://eed3si9n.com/learning-scalaz-day13
For your specific examples, for 3.failure[String] you'd need:
import scalaz.syntax.validation._
Validation already has a method ap:
scala> "hello".successNel[Int] ap ((s: String) => "x"+s).successNel[Int]
res1: scalaz.Validation[scalaz.NonEmptyList[Int],java.lang.String] = Success(xhello)
To get the <*> operator, you need this import:
import scalaz.syntax.applicative._
Then you can do:
"hello".successNel[Int] <*> ((s: String) => "x"+s).successNel[Int]