I have a class that has a one parameter method that produces a result and returns an object like itself but with updated state for subsequent use.
For example, below contains a simple example of such a class and how I might use it:
case class Foo(x: Double) {
def bar(y: Double): (Foo, Double) = (Foo(x + y), x / (x + y))
}
val res = Vector(1.0,2.0,3.0,4.0).foldLeft((Foo(0), 0.0))((foo, x) => foo._1.bar(x))
res._1.bar(3.0)
I have looked at the Cats State monad and was hopeful that I could use it to avoid threading the state (the "x" member) around. The examples here are close to what I want but the function that returns the new state does not have any parameters and state is not passed around in a loop-like operation (instead it's passed between expressions). I am a complete novice when it comes to Cats but am I barking up the wrong tree?
Below you can find the way how cats state monad can be adapated to your case. However I had some problems with sequencing List[State[S, A]] to have State[S, List[A]] in cats, so I have written a function sequence for that. If someone knew how to do that I would be interested :)
import cats.data._
case class Foo(x: Double)
def bar(y: Double): State[Foo, Double] = for {
foo <- State.get[Foo]
_ <- State.set(Foo(foo.x + y))
} yield foo.x / (foo.x + y)
val xs: List[State[Foo, Double]] = List(1.0, 2.0, 3.0, 4.0).map(bar)
def sequence(xs: List[State[Foo, Double]]): State[Foo, List[Double]] =
xs.foldLeft(State.pure[Foo, List[Double]](List.empty[Double])) { (acc, x) =>
for {
xs <- acc
xx <- x
} yield xx :: xs
}
val s = sequence(xs)
val ss = s.map(_.head)
s.run(Foo(0)).value
ss.run(Foo(0)).value
ss.flatMap(_ => bar(3)).run(Foo(0)).value
In result you get
res0: (Foo, List[Double]) = (Foo(10.0),List(0.6, 0.5, 0.3333333333333333, 0.0))
res1: (Foo, Double) = (Foo(10.0),0.6)
res2: (Foo, Double) = (Foo(13.0),0.7692307692307693)
Related
I was looking at Dotty docs under Contextual Abstractions page and I saw the Given Instances.
Given instances (or, simply, "givens") define "canonical" values of
certain types that serve for synthesizing arguments to given clauses.
Example:
trait Ord[T] {
def compare(x: T, y: T): Int
def (x: T) < (y: T) = compare(x, y) < 0
def (x: T) > (y: T) = compare(x, y) > 0
}
given intOrd: Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) +1 else 0
}
given listOrd[T]: (ord: Ord[T]) => Ord[List[T]] {
def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match {
case (Nil, Nil) => 0
case (Nil, _) => -1
case (_, Nil) => +1
case (x :: xs1, y :: ys1) =>
val fst = ord.compare(x, y)
if (fst != 0) fst else compare(xs1, ys1)
}
}
But this example from docs never explains how to use given. I pulled the test Dotty example project and try yo use it, but I don't quite understand it.
Is it a new keyword ? Do we import it ? Or am I missing something .
Here's an example of using the given instance. Let's say we want to compare two integers, and see which is bigger than the other. We can leverage the already defined intOrd above and write:
def whichIsBigger[T](x: T, y: T)(given ord: Ord[T]): String = {
ord.compare(x, y) match {
case -1 => s"$x is less than $y"
case 0 => s"$x and $y are equal"
case 1 => s"$x is greater than $y"
}
}
println(whichIsBigger(2, 1))
Which yields:
2 is greater than 1
We were able to do this because there was a named given instance in scope, otherwise, the compiler would have complained it doesn't have an Ord[Int].
Is it a new keyword ? Do we import it ? Or am I missing something.
It is a new keyword, one which replaces a specific part of implicit definition in Scala 2. If this was Scala 2, we would have written:
implicit val intOrd: Ord[Int] = new Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) 1 else 0
}
def whichIsBigger[T](x: T, y: T)(implicit ord: Ord[T]): String
Perhaps it would be instructive to compare how we might define a typeclass using implicit keyword in Scala 2 versus using given keyword in Scala 3:
Scala 2
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A: Semigroup](x: A, y: A) = implicitly[Semigroup[A]].combine(x,y)
implicit val intSemigroup: Semigroup[Int] = new Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
implicit val quxSemigroup: Semigroup[Qux] = new Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1)
Semigroup.combine(Qux(41), Qux(1))
Scala 3
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A](x: A, y: A)(given Semigroup[A]) = summon.combine(x,y)
given intSemigroup: Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
given quxSemigroup: Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1))
Semigroup.combine(Qux(41), Qux(1))
Yes, it's a new keyword, as you can tell from 'given' being used in the grammar at the end of the page (section "Syntax"). It is intended to replace implicit. If you are already familiar with implicits, I think Relationship with Scala 2 Implicits is good to start with.
For simplicity sake let's assume my HList instance holds exactly 2 values:
def intToString(x: Int) = x + "_"
def intToDouble(x: Int) = x * 10d
val fns = (intToString _ :: intToDouble _ :: HNil)
Now I'd like, having some Hlist of ints, to be able to do this:
(fns zip (1 :: 2 :: HList) map {case (f, x) => f(x) }
to get
("1_", 10.0)
From now on, assume that I don't know what I am doing and I totally understand all my paltriness in the faces of the functional gods.
I already looked at shapeless' wiki and, as far as I understood, I should make a function from Int to T that can be accepted by shapeless. Did I understood correct? Here's what I got:
object mapApply extends Poly1 {
implicit def default[T] = at[Function[Int,T]](f => f.apply _)
}
At this point I'm completely lost and don't even have a clue of how to proceed. But I'm kinda fascinated by the potential power and expressiveness that this could deliver, so I'd really like to understand how this stuff works. I would really appreciate if your answers will not be just code snippets but rather more open and explanatory.
P.S. SO's engine just suggested me a c++ tag. Did I say something C++-ish?
It looks like you're mixing method and function definition syntax—I'll assume you meant something like the following:
val intToString = (x: Int) => x + "_"
val intToDouble = (x: Int) => x * 10d
val fns = intToString :: intToDouble :: HNil
Now you can use zipApply, which just pairs functions and their arguments:
val res = fns.zipApply(1 :: 2 :: HNil)
If for some reason zipApply didn't exist, you could accomplish the same thing with a Poly1:
object apply extends Poly1 {
implicit def default[I, O]: Case.Aux[(I => O, I), O] =
at[(I => O, I)] { case (f, x) => f(x) }
}
val res = fns.zip(1 :: 2 :: HNil).map(apply)
Or this, if you don't want the extra genericity:
object applyToInt extends Poly1 {
implicit def default[T]: Case.Aux[(Int => T, Int), T] =
at[(Int => T, Int)] { case (f, x) => f(x) }
}
So you weren't too far off—you just needed to have a case in your Poly1 for the pair of the function and the argument, not just the function.
Why does andThen only exist for single argument functions in Scala?
The following code works:
val double = (x: Int) => x * 2
val timesFour = double andThen double
But why is there no andThen method for multi argument functions?
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
<console>:10: error: value andThen is not a member of (Int, Int) => Int
Surely it is trivial to add this method. Is there a reason it been omitted from the standard library?
I have just noticed it is easy to work around with the following:
val multiplyAndDouble = multiply.tupled andThen double
val res = multiplyAndDouble(1, 3) // res = 6
I can't speak as to why Function2 doesn't supply and andThen, but Scalaz defines Functor instances for functions of various arities where map is equivalent to andThen, meaning you could write
val multiplyAndDouble = multiply map double
There is a similar question here:
Scala API 2.10.*: Function2.andThen what happened to?, but there is also no answer. In my opinion it is possible. Here is working example for Scala 2.11.1:
object TestFunction2 {
def main(args: Array[String]): Unit = {
val double = (x: Int) => x * 2
val timesFour = double andThen double
println(timesFour(2)) // prints 8
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
println(multiplyAndDouble(1, 3)) // prints 6
}
implicit def toFunc2(function2: Function2[Int, Int, Int]): Func2[Int, Int, Int] = {
new Func2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = function2(v1, v2)
}
}
}
trait Func2[-T1, -T2, +R] extends Function2[T1, T2, R] {
def andThen[A](g: R => A): (T1, T2) => A = { (x, y) => g(apply(x, y)) }
}
Another way to write theons's answer is to use:
val multiplyAndDouble = double compose multiply.tupled
val result = multiplyAndDouble(2, 6) // res 24
How would you find minValue below?
I have my own solution but want to see how others would do it.
val i1: Option[Int] = ...
val i2: Option[Int] = ...
val defaultValue: Int = ...
val minValue = ?
Update: I just noticed that my solution below and the one in your answer behave differently—I read your question as asking for the minimum of the two values when there are two values, but in your answer you're effectively treating None as if it contained a value that's either bigger (for min) or smaller (for max) than anything else.
To be more concrete: if i1 is Some(1) and i2 is None, my solution will return the default value, while yours will return 1.
If you want the latter behavior, you can use the default semigroup instance for Option[A] and the tropical semigroup for Int. In Scalaz 7, for example, you'd write:
import scalaz._, Scalaz._
optionMonoid(Semigroup.minSemigroup[Int]).append(i1, i2) getOrElse defaultValue
Or the following shorthand:
Tags.Min(i1) |+| Tags.Min(i2) getOrElse defaultValue
It's not as clean as the applicative functor solution below, but if that's your problem, that's your problem.
Here's a more idiomatic way that doesn't involve creating an extra list:
(for { x <- i1; y <- i2 } yield math.min(x, y)) getOrElse defaultValue
Or, equivalently:
i1.flatMap(x => i2.map(math.min(x, _))) getOrElse defaultValue
What you're doing is "lifting" a two-place function (min) into an applicative functor (Option). Scalaz makes this easy with its applicative builder syntax:
import scalaz._, Scalaz._
(i1 |#| i2)(math.min) getOrElse defaultValue
The standard library solution isn't much less elegant in this case, but this is a useful abstraction to know about.
I solved a similar problem using the following approach. We handle a special case when both of the options have values, otherwise we use an API method Option.orElse.
val a: Option[Int] = Some(10)
val b: Option[Int] = Some(20)
val c: Option[Int] = (a, b) match {
case (Some(x), Some(y)) => Some(x min y)
case (x, y) => x orElse y
}
I think this is what you're after:
val minValue = List(i1, i2).flatten match {
case Nil => defaultValue
case xs => xs.min
}
I'd avoid sorted since sorting requires a lot more processing than simply finding the max or min (although it probably doesn't make much difference in this case).
val minValue: Int = List(i1, i2).flatten.sorted.headOption getOrElse defaultValue
You can use patterns in for expressions, values that do not match the pattern are discarded.
(for (Some(x) <- List(None, Some(3))) yield x) max
Not as good as the List.flatten approach though.
Another option which wasn't mentioned is using reduceLeftOption (interchange math.max and math.min as desired):
val min = (first ++ second).reduceLeftOption(math.min).getOrElse(defaultValue)
scala> val first = Some(10)
first: Some[Int] = Some(10)
scala> val second: Option[Int] = None
second: Option[Int] = None
scala> val defaultMin = -1
defaultMin: Int = -1
scala> (first ++ second).reduceLeftOption(math.min).getOrElse(defaultMin)
res7: Int = 10
scala> val first: Option[Int] = None
first: Option[Int] = None
scala> (first ++ second).reduceLeftOption(math.min).getOrElse(defaultMin)
res8: Int = -1
scala> val first = Some(10)
first: Some[Int] = Some(10)
scala> val second = Some(42)
second: Some[Int] = Some(42)
scala> (first ++ second).reduceLeftOption(math.min).getOrElse(defaultMin)
res9: Int = 10
We can combine the 2 Options as an Iterable with Option's ++ operator, which allows us to use minOption (to nicely handle the case of the empty iterable formed by the None/None case) and fallback on a default value if necessary with getOrElse:
(optionA ++ optionB).minOption.getOrElse(-1)
// None and None => -1
// Some(5) and None => 5
// None and Some(5) => 5
// Some(5) and Some(3) => 3
If you want to avoid using scalaz and map/for/getOrElse, you can do the following:
val minValue = (i1, i2) match {
case (Some(x), Some(y)) => math.min(x, y)
case _ => defaultValue
}
tl;dr
You can do that you need elegant using custom cats Semigroup instances:
import cats.kernel.Semigroup
import cats.instances.option._ // this import is for cats std option combiner
import cats.syntax.semigroup._
object Implicits {
implicit val intMinSemigroup: Semigroup[Int] =
(x: Int, y: Int) => math.min(x, y)
implicit val intMaxSemigroup: Semigroup[Int] =
(x: Int, y: Int) => math.max(x, y)
}
import Implicits.intMinSemigroup
// these are results for minSemigroup
// List((Some(1),Some(1),Some(2)), (Some(1),Some(1),None), (None,Some(2),Some(2)), (None,None,None))
//import Implicits.intMaxSemigroup
// these are results for maxSemigroup
// List((Some(1),Some(2),Some(2)), (Some(1),Some(1),None), (None,Some(2),Some(2)), (None,None,None))
for {
maybeA <- Seq(Some(1), None)
maybeB <- Seq(Some(2), None)
} yield (maybeA, maybeA |+| maybeB, maybeB)
if you want replace None by default value you can use combine twice:
val defaultValue: Int = 3
val optionMin = for {
maybeA <- Seq(Some(1), None)
maybeB <- Seq(Some(2), None)
} yield (maybeA |+| maybeB) |+| Some(defaultValue)
// List(Some(1), Some(1), Some(2), Some(3))
How it works
Shortly, Semigroup[A] is typeclass for combining two values of the same type A into the one value of type A.
Here we use std cats OptionMonoid (it extends Semigroup[Option[A]]) here source code:
class OptionMonoid[A](implicit A: Semigroup[A]) extends Monoid[Option[A]] {
def empty: Option[A] = None
def combine(x: Option[A], y: Option[A]): Option[A] =
x match {
case None => y
case Some(a) =>
y match {
case None => x
case Some(b) => Some(A.combine(a, b))
}
}
}
We see that it takes option matching on his own and everything what we should give him to work is implicit A: Semigroup[A]. In our case we write two different combiners for min, max cases:
object Implicits {
implicit val intMinSemigroup: Semigroup[Int] =
(x: Int, y: Int) => math.min(x, y)
implicit val intMaxSemigroup: Semigroup[Int] =
(x: Int, y: Int) => math.max(x, y)
}
So, we import combiners (i.e. import Implicits.intMinSemigroup) and just use cats.syntax.semigroup for using combine function as operator |+|:
maybeA |+| maybeB.
In conclusion, you can just define your custom semigroup for any type (not only Int) and combine options of this type after importing some cats syntax and instances.
In Scala, the PartialFunction[A, B] class is derived from type Function[A, B] (see Scala Reference, 12.3.3). However, this seems counterintuitive to me, since a Function (which needs to be defined for all A) has more stringent requirements than a PartialFunction, which can be undefined at some places.
The problem I've come across is that when I have a partial function, I cannot use a Function to extend the partial function. Eg. I cannot do:
(pf orElse (_)=>"default")(x)
(Hope the syntax is at least remotely right)
Why is this subtyping done reversely? Are there any reasons that I've overlooked, like the fact that the Function types are built-in?
BTW, it would be also nice if Function1 :> Function0 so I needn't have the dummy argument in the example above :-)
Edit to clarify the subtyping problem
The difference between the two approaches can be emphasized by looking at two examples. Which of them is right?
One:
val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?
Two:
def foo(f : (Int)=>Int) {
print(f(1))
}
val bar = new PartialFunction[Int, Int] {
def apply(x : Int) = x/2
def isDefinedAt(x : Int) = x%2 == 0
}
foo(bar) // should this be a breach of promise?
Because in Scala (as in any Turing complete language) there is no guarantee that a Function is total.
val f = {x : Int => 1 / x}
That function is not defined at 0. A PartialFunction is just a Function that promises to tell you where it's not defined. Still, Scala makes it easy enough to do what you want
def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)}
val pf : PartialFunction[Int, String] = {case 1 => "one"}
val g = pf orElse func2Partial{_ : Int => "default"}
scala> g(1)
res0: String = one
scala> g(2)
res1: String = default
If you prefer, you can make func2Partial implicit.
PartialFunction has methods which Function1 does not, therefore it is the subtype. Those methods are isDefinedAt and orElse.
Your real problem is that PartialFunctions are not inferred sometimes when you'd really like them to be. I'm hopeful that will be addressed at some future date. For instance this doesn't work:
scala> val pf: PartialFunction[String, String] = { case "a" => "foo" }
pf: PartialFunction[String,String] = <function>
scala> pf orElse { case x => "default" }
<console>:6: error: missing parameter type for expanded function
((x0$1) => x0$1 match { case (x # _) => "default" })
But this does:
scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>
Of course you could always do this:
scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] =
new PartialFunction[T,R] {
def apply(x: T) = f(x)
def isDefinedAt(x: T) = true
}
f2pf: [T,R](f: (T) => R)PartialFunction[T,R]
And now it's more like you want:
scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>
scala> println(res7("a") + " " + res7("quux"))
foo default