Different Behavior with (Cats) Functor in Scala-REPL and Compilation - scala-cats

import cats.{Functor, Monoid}
trait Fold[I, O] {
type M
def m: Monoid[M]
def tally: I => M
def summarize: M => O
}
object Fold {
def apply[I, O, _M](_m: Monoid[_M])(_tally: I => _M, _summarize: _M => O): Fold[I, O] = new Fold[I, O] {
override type M = _M
override def m = _m
override def tally = _tally
override def summarize = _summarize
}
}
object BeautifulFold extends App {
def fold[I, O](input: Seq[I])(f: Fold[I, O]): O =
f.summarize(input.foldLeft(f.m.empty)((x, y) => f.m.combine(x, f.tally(y))))
def sum[M](implicit ev: Monoid[M]): Fold[M, M] = Fold.apply(ev)(identity, identity)
implicit def foldFunctor[I] = new Functor[({type F[X] = Fold[I, X]})#F] {
override def map[A, B](fa: Fold[I, A])(f: A => B): Fold[I, B] =
Fold(fa.m)(fa.tally, fa.summarize.andThen(f))
}
import cats.implicits._
fold(List(1,2,3))(sum)
fold(List(1,2,3))((sum[Int]:Fold[Int,Int]).map(s => s"Sum is $s"))
}
works perfectly in REPL :paste mode but it throws an error,
[error] value map is not a member of Fold[Int,Int]
[error] fold(List(1,2,3))((sum[Int]:Fold[Int,Int]).map(s => s"Sum is $s"))
during sbt compile. SBT version is 1.1.0
The partial settings for build.sbt are,
scalaVersion := "2.12.4"
val catsVer = "1.1.0"
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature", "-Xlog-implicits", "-Ypartial-unification")
libraryDependencies in ThisBuild ++= Seq(
"org.typelevel" %% "cats-core" % catsVer,
"org.typelevel" %% "cats-macros" % catsVer,
"org.typelevel" %% "cats-kernel" % catsVer,
"org.typelevel" %% "cats-free" % catsVer,
...
What is wrong with my compilation setting? Thanks.
Update 1
There is nothing wrong with this code snippet. What I did wrong was I didn't include -Ypartial-unification to scalacOptions in my actual project like I did here. And there is also another thing, please refer to the answer.

It is important to include -Ypartial-unification option to scalacOptions, as mentioned in Cats README file. It is also important how it is done if you have a multi modules project. The option should be added to modules that require this option. If it is preferable to be a global option, please put it in the common settings list, as in,
lazy val commonSettings = Seq(
organization := "org.teckhooi",
version := "1.0-SNAPSHOT",
publishArtifact in (Compile, packageDoc) := false,
publishArtifact in packageDoc := false,
sources in(Compile, doc) := Seq.empty,
logLevel := util.Level.Info,
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature", "-Xlog-implicits", "-Ypartial-unification")
)
lazy val root = project aggregate(foo, bar)
lazy val foo = project.settings(commonSettings)
lazy val bar = project.settings(commonSettings)
)

Related

Scala string interpolation with a pass-by-name string

I'd like to pass a default string to a function and have "string interpolation" done on it in the function rather than at the call site.
For example,
def isBetween(a:Int, b:Int,
msg: String = s"${v} is not between ${a} and ${b}."
)(v:Int):Either[String, Boolean] = {
if (a <= v && v <= b) Right(true) else Left(msg)
}
This doesn't compile because none of a, b, and for sure not v are in scope when the compiler wants to do the interpolation.
The goal is to provide a default error string but allow the user to change it, if necessary. For example:
val normalBetween = isBetween(0, 100)
val customBetween = isBetween(0, 100, s"Doofus! it's gotta be ${a} <= v <= ${b} but v is ${v}!")
val result1 = normalBetween(101) // Left("101 is not between 0 and 100.")
val result2 = customBetween(101) // Left("Doofus! it's gotta be 0 <= v <= 100 but v is 101!")
I tried making msg pass-by-name; no luck.
I suppose I want something like this from the Python world:
name = 'world'
program ='python'
print('Hello {name}!This is{program}.'.format(name=name, program=program))
Any suggestions?
As #LuisMiguelMejíaSuárez suggested in the comment, you can just use java's string formatting:
def isBetween(a: Int, b: Int, msg: String = "%%d is not between %d and %d.")(v: Int): Either[String, Boolean] = {
if (a <= v && v <= b) Right(true) else Left(msg.format(a, b).format(v))
}
def normalBetween: Int => Either[String, Boolean] = isBetween(0, 100)
def customBetween: Int => Either[String, Boolean] = isBetween(0, 100, "Doofus! it's gotta be %d <= v <= %d but v is %%d!")
val result1 = normalBetween(101) // Left("101 is not between 0 and 100.")
val result2 = customBetween(101) // Left("Doofus! it's gotta be 0 <= v <= 100 but v is 101!")
println(result1)
println(result2)
The result will be as expected. Code run at Scastie. If you are taking this approach, and your scenario inn reality is more complex than the given example, you can use named parameters in this string. More can be read about it at Named placeholders in string formatting, How to format message with argument names instead of numbers?, and many more articles.
It's not possible to refer to a variable declared in the same (or a future) parameter list, however you can refer to a variable declared in a previous parameter list, like so:
def isBetween(
a:Int, b:Int
)(v: Int)(
msg: String = s"${v} is not between ${a} and ${b}."
): Either[String, Boolean] = {
if (a <= v && v <= b) Right(true) else Left(msg)
}
If you'd like to be able to offer callers the ability to provide a custom template string, you can do so as follows:
def isBetween(
a:Int, b:Int
)(v: Int)(
msg: (Int, Int, Int) => String =
(pA, pB, pV) => s"${pV} is not between ${pA} and ${pB}."
): Either[String, Boolean] = {
if (a <= v && v <= b) Right(true) else Left(msg(a, b, v)
}
Example usage:
val customMsg = (a: Int, b: Int, v: Int) => s"Sorry but $v is not between $a and $b!"
isBetween(5, 7)(6)(customMsg)
If you'd like to offer callers a completely "custom" isBetween, then you can do so by putting the message in the first parameter group:
def isBetween(
msg: (Int, Int, Int) => String =
(pA, pB, pV) => s"${pV} is not between ${pA} and ${pB}."
)(
a:Int, b:Int
)(v: Int): Either[String, Boolean] = {
if (a <= v && v <= b) Right(true) else Left(msg(a, b, v))
}
val customMsg = (a: Int, b: Int, v: Int) => s"Sorry but $v is not between $a and $b!"
val customMsgIsBetween = isBetween(customMsg) _
customMsgIsBetween(5, 7)(6)
It's worth remembering that we can use sentinel values for this. While null is discouraged in Scala for passing data around, it is still allowed, and for a temporary local use, it's fairly harmless as long as we don't let it escape scope.
def isBetween(a: Int, b: Int, msgArg: String = null)(v: Int): Either[String, Boolean] = {
val msg = if (msgArg == null) {
s"${v} is not between ${a} and ${b}.";
} else {
msgArg
}
if (a <= v && v <= b) {
Right(true)
} else {
Left(msg)
}
}

How to pass function output in futures and then those futures to a new function?

My Scenario is like below:
Step1: x =def sum(a,b)
Step2: Thread.sleep(1s)
Step3: y =def subtract(a,b)
Step4: Thread.sleep(2s)
Step5: On successfull completion of above steps perform z = multiple(x,y)
I need to implement this scenario using futures in Scala. Please help.
I Tried this code but it is not working.
import scala.util.{Failure, Success}
def sum(a:Int ,b:Int) = a+b
def sub(c:Int, d:Int) = c-d
def mul(e: Int, f: Int) = e*f
val Sum1= Future {sum(2,3); Thread.sleep(1000)}
val SumFinal=Sum1.onComplete({
case Success(result) => println(result)
case Failure(e) => println("failed: " + e)
})
val Subt1 = Future {sub(5,3);Thread.sleep(2000)}
val SubtFinal = Subt1.onComplete({
case Success(result) => result
case Failure(e) => println("failed: " + e)
})
val Mul1= mul(SumFinal,SubtFinal)
println(Mul1)
Problem with your approach is that onComplete returns unit. That's why you don't get any result. So, subFimal and sumFinal has nothing in it.
scala> def sum(a: Int, b: Int) = Future { a + b }
sum: (a: Int, b: Int)scala.concurrent.Future[Int]
scala> def sub(a: Int, b: Int) = Future { a - b }
sub: (a: Int, b: Int)scala.concurrent.Future[Int]
scala> def mul(a: Int, b: Int) = Future { a * b }
mul: (a: Int, b: Int)scala.concurrent.Future[Int]
scala> for {
| a <- sum(2,3)
| b <- sub(10, 7)
| c <- mul(a, b)
| } yield c
res0: scala.concurrent.Future[Int] = Future(<not completed>)
scala> res0
res1: scala.concurrent.Future[Int] = Future(Success(15))
Problem 1:
The result of e.g. Future {sub(5,3);Thread.sleep(2000)} is the value returned by Thread.sleep, which is () in Scala. Just change the order: Future {Thread.sleep(2000); sub(5,3)} will finish with the result 2 after 2 seconds. If you really want to put sleep after the calculation, just store the result in a variable:
Future {
val res = sub(5,3)
Thread.sleep(2000)
res
}
Problem 2:
SumFinal and SubtFinal are again () because that's what onComplete returns. Instead you can combine two futures (or more, or modify one, etc. etc.) and get a future back. One way would be (after fixing problem 1)
val Mul1 = Sum1.zipWith(Sum2)(mul)
Mul1.onComplete {
...
}

How to use scala strings in list-like pattern matching

So I was reading up about how scala lets you treat string as a sequence of chars through its implicit mechanism. I created a generic Trie class for a general element type and wanted to use it's Char based implementation with string like syntax.
import collection.mutable
import scala.annotation.tailrec
case class Trie[Elem, Meta](children: mutable.Map[Elem, Trie[Elem, Meta]], var metadata: Option[Meta] = None) {
def this() = this(mutable.Map.empty)
#tailrec
final def insert(item: Seq[Elem], metadata: Meta): Unit = {
item match {
case Nil =>
this.metadata = Some(metadata)
case x :: xs =>
children.getOrElseUpdate(x, new Trie()).insert(xs, metadata)
}
}
def insert(items: (Seq[Elem], Meta)*): Unit = items.foreach { case (item, meta) => insert(item, meta) }
def find(item: Seq[Elem]): Option[Meta] = {
item match {
case Nil => metadata
case x :: xs => children.get(x).flatMap(_.metadata)
}
}
}
object Trie extends App {
type Dictionary = Trie[Char, String]
val dict = new Dictionary()
dict.insert( "hello", "meaning of hello")
dict.insert("hi", "another word for hello")
dict.insert("bye", "opposite of hello")
println(dict)
}
Weird thing is, it compiles fine but gives error on running:
Exception in thread "main" scala.MatchError: hello (of class scala.collection.immutable.WrappedString)
at Trie.insert(Trie.scala:11)
at Trie$.delayedEndpoint$com$inmobi$data$mleap$Trie$1(Trie.scala:34)
at Trie$delayedInit$body.apply(Trie.scala:30)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at Trie$.main(Trie.scala:30)
at Trie.main(Trie.scala)
It's able to implicitly convert String to WrappedString, but that doesn't match the ::. Any workarounds for this?
You can use startsWith as follows:
val s = "ThisIsAString"
s match {
case x if x.startsWith("T") => 1
case _ => 0
}
Or convert your String to List of chars with toList
scala> val s = "ThisIsAString"
s: String = ThisIsAString
scala> s.toList
res10: List[Char] = List(T, h, i, s, I, s, A, S, t, r, i, n, g)
An then use it as any other List
s.toList match {
case h::t => whatever
case _ => anotherThing
}
Your insert method declares item to be a Seq, but your pattern match only matches on List. A string can be implicitly converted to a Seq[Char], but it isn't a List. Use a pattern match on Seq instead of List using +:.
#tailrec
final def insert(item: Seq[Elem], metadata: Meta): Unit = {
item match {
case Seq() =>
this.metadata = Some(metadata)
case x +: xs =>
children.getOrElseUpdate(x, new Trie()).insert(xs, metadata)
}
}
The same applies to your find method.

How to handle optional db step in slick 3?

I'm sure I'm simply facing a mental block with the functional model of Slick 3, but I cannot discern how to transactionally sequence an optional dependent db step in Slick 3. Specifically, I have a table with an optional (nullable) foreign key and I want it to be set to the ID of the inserted dependent record (if any, else null). That is, roughly:
if ( x is non null )
start transaction
id = insert x
insert y(x = id)
commit
else
start transaction
insert y(x = null)
commit
Of course, I'd rather not have the big if around the choice. Dependencies without the Option[] seem (relatively) straightforward, but the option is throwing me.
Precise example code (sans imports) follows. In this example, the question is how to save both x (a) and y (b) in the same transaction both if y is None or not. Saving Y itself seems straightforward enough as every related C has a non-optional B reference, but addressing the optional reference in A is unclear (to me).
object test {
implicit val db = Database.forURL("jdbc:h2:mem:DataTableTypesTest;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
/* Data model */
case class A(id: Long, b: Option[Long], s: String)
class As(tag: Tag) extends Table[A](tag, "As") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def b = column[Option[Long]]("B")
def s = column[String]("S")
def * = (id, b, s) <> (A.tupled, A.unapply)
}
val as = TableQuery[As]
case class B(id: Long, s: String)
class Bs(tag: Tag) extends Table[B](tag, "Bs") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def s = column[String]("S")
def * = (id, s) <> (B.tupled, B.unapply)
}
val bs = TableQuery[Bs]
case class C(id: Long, b: Long, s: String)
class Cs(tag: Tag) extends Table[C](tag, "Cs") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def b = column[Long]("B")
def s = column[String]("S")
def * = (id, b, s) <> (C.tupled, C.unapply)
}
val cs = TableQuery[Cs]
/* Object model */
case class X(id: Long, s: String, y: Option[Y])
case class Y(id: Long, s: String, z: Set[Z])
case class Z(id: Long, s: String)
/* Mappers */
def xToA(x: X, bId: Option[Long]): A = { A(x.id, bId, x.s) }
def yToB(y: Y): B = { B(y.id, y.s) }
def zToC(z: Z, bId: Long): C = { C(z.id, bId, z.s) }
/* Given */
val example1 = X(0, "X1", Some(Y(0, "Y1", Set(Z(0, "Z11"), Z(0, "Z12")))))
val example2 = X(0, "X2", Some(Y(0, "Y2", Set())))
val example3 = X(0, "X3", None)
Await.result(db.run((as.schema ++ bs.schema ++ cs.schema).create), 10.seconds)
val examples = Seq(example1, example2, example3)
for ( example <- examples ) {
val saveY = (for { y <- example.y }
yield ( for {
id <- (bs returning bs.map(_.id)) += yToB(y)
_ <- cs ++= y.z.map(zToC(_, id))
} yield id) transactionally)
if ( saveY.isDefined ) Await.result(db.run(saveY.get), 10.seconds)
}
println(Await.result(
db.run(
(for { a <- as } yield a).result
),
10.seconds
))
println(Await.result(
db.run(
(for { b <- bs } yield b).result
),
10.seconds
))
println(Await.result(
db.run(
(for { c <- cs } yield c).result
),
10.seconds
))
}
This is fairly straightforward; just use the monadic-ness of DBIO:
// Input B value; this is your `x` in the question.
val x: Option[B] = _
// Assume `y` is fully-initialized with a `None` `b` value.
val y: A = _
// DBIO wrapping the newly-inserted ID, if `x` is set.
val maybeInsertX: DBIO[Option[Int]] = x match {
case Some(xToInsert) =>
// Insert and return the new ID.
val newId: DBIO[Int] = bs.returning(bs.map(_.id)) += xToInsert
// Map to the expected Option.
newId.map(Some(_))
case None =>
// No x means no ID.
DBIO.successful(None)
}
// Now perform your insert, copying in the newly-generated ID.
val insertA: DBIO[Int] = maybeInsertX.flatMap(bIdOption =>
as += y.copy(b = bIdOption)
)
// Run transactionally.
db.run(insertA.transactionally)

Mapping sub-sets of parentheses to chars

I am attempting to create a Scala method that will take one parent group of parentheses, represented as a String, and then map each subgroup of parentheses to a different letter. It should then put these in a map which it returns, so basically I call the following method like this:
val s = "((2((x+3)+6)))"
val map = mapParentheses(s)
Where s could contain any number of sets of parentheses, and the Map returned should contain:
"(x+3)" -> 'a'
"(a+6)" -> 'b'
"(2b)" -> 'c'
"(c)" -> 'd'
So that elsewhere in my program I can recall 'd' and get "(c)" which will become "((2b))" then ((2(a+6))) and finally ((2((x+3)+6))). The string sent to the method mapParentheses will never have unmatched parentheses, or extra chars outside of the main parent parentheses, so the following items will never be sent:
"(fsf)a" because the a is outside the parent parentheses
"(a(aa))(a)" because the (a) is outside the parent parentheses
"((a)" because the parentheses are unmatched
")a(" because the parentheses are unmatched
So I was wondering if anyone knew of an easy (or not easy) way of creating this mapParentheses method.
You can do this pretty easily with Scala's parser combinators. First for the import and some simple data structures:
import scala.collection.mutable.Queue
import scala.util.parsing.combinator._
sealed trait Block {
def text: String
}
case class Stuff(text: String) extends Block
case class Paren(m: List[(String, Char)]) extends Block {
val text = m.head._2.toString
def toMap = m.map { case (k, v) => "(" + k + ")" -> v }.toMap
}
I.e., a block represents a substring of the input that is either some non-parenthetical stuff or a parenthetical.
Now for the parser itself:
class ParenParser(fresh: Queue[Char]) extends RegexParsers {
val stuff: Parser[Stuff] = "[^\\(\\)]+".r ^^ (Stuff(_))
def paren: Parser[Paren] = ("(" ~> insides <~ ")") ^^ {
case (s, m) => Paren((s -> fresh.dequeue) :: m)
}
def insides: Parser[(String, List[(String, Char)])] =
rep1(paren | stuff) ^^ { blocks =>
val s = blocks.flatMap(_.text)(collection.breakOut)
val m = blocks.collect {
case Paren(n) => n
}.foldLeft(List.empty[(String, Char)])(_ ++ _)
(s, m)
}
def parse(input: String) = this.parseAll(paren, input).get.toMap
}
Using get in the last line is very much not ideal, but is justified by your assertion that we can expect well-formed input.
Now we can create a new parser and pass in a mutable queue with some fresh variables:
val parser = new ParenParser(Queue('a', 'b', 'c', 'd', 'e', 'f'))
And now try out your test string:
scala> println(parser parse "((2((x+3)+6)))")
Map((c) -> d, (2b) -> c, (a+6) -> b, (x+3) -> a)
As desired. A more interesting exercise (left to the reader) would be to thread some state through the parser to avoid the mutable queue.
Classic recursive parsing problem. It can be handy to hold the different bits. We'll add a few utility methods to help us out later.
trait Part {
def text: String
override def toString = text
}
class Text(val text: String) extends Part {}
class Parens(val contents: Seq[Part]) extends Part {
val text = "(" + contents.mkString + ")"
def mapText(m: Map[Parens, Char]) = {
val inside = contents.collect{
case p: Parens => m(p).toString
case x => x.toString
}
"(" + inside.mkString + ")"
}
override def equals(a: Any) = a match {
case p: Parens => text == p.text
case _ => false
}
override def hashCode = text.hashCode
}
Now you need to parse into these things:
def str2parens(s: String): (Parens, String) = {
def fail = throw new Exception("Wait, you told me the input would be perfect.")
if (s(0) != '(') fail
def parts(s: String, found: Seq[Part] = Vector.empty): (Seq[Part], String) = {
if (s(0)==')') (found,s)
else if (s(0)=='(') {
val (p,s2) = str2parens(s)
parts(s2, found :+ p)
}
else {
val (tx,s2) = s.span(c => c != '(' && c != ')')
parts(s2, found :+ new Text(tx))
}
}
val (inside, more) = parts(s.tail)
if (more(0)!=')') fail
(new Parens(inside), more.tail)
}
Now we've got the whole thing parsed. So let's find all the bits.
def findParens(p: Parens): Set[Parens] = {
val inside = p.contents.collect{ case q: Parens => findParens(q) }
inside.foldLeft(Set(p)){_ | _}
}
Now we can build the map you want.
def mapParentheses(s: String) = {
val (p,_) = str2parens(s)
val pmap = findParens(p).toSeq.sortBy(_.text.length).zipWithIndex.toMap
val p2c = pmap.mapValues(i => ('a'+i).toChar)
p2c.map{ case(p,c) => (p.mapText(p2c), c) }.toMap
}
Evidence that it works:
scala> val s = "((2((x+3)+6)))"
s: java.lang.String = ((2((x+3)+6)))
scala> val map = mapParentheses(s)
map: scala.collection.immutable.Map[java.lang.String,Char] =
Map((x+3) -> a, (a+6) -> b, (2b) -> c, (c) -> d)
I will leave it as an exercise to the reader to figure out how it works, with the hint that recursion is a really powerful way to parse recursive structures.
def parse(s: String,
c: Char = 'a', out: Map[Char, String] = Map() ): Option[Map[Char, String]] =
"""\([^\(\)]*\)""".r.findFirstIn(s) match {
case Some(m) => parse(s.replace(m, c.toString), (c + 1).toChar , out + (c -> m))
case None if s.length == 1 => Some(out)
case _ => None
}
This outputs an Option containing a Map if it parses, which is better than throwing an exception if it doesn't. I suspect you really wanted a map from Char to the String, so that's what this outputs. c and out are default parameters so you don't need to input them yourself. The regex just means "any number of characters that aren't parens, eclosed in parens" (the paren characters need to be escaped with "\"). findFirstIn finds the first match and returns an Option[String], which we can pattern match on, replacing that string with the relevant character.
val s = "((2((x+3)+6)))"
parse(s) //Some(Map(a -> (x+3), b -> (a+6), c -> (2b), d -> (c)))
parse("(a(aa))(a)") //None

Resources