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.
Related
I'm trying to do the following:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42 = (y: Int) => divide((42, y))
However:
divide42.isDefinedAt(0)
cmd18.sc:1: value isDefinedAt is not a member of Int => Int
val res18 = divide42.isDefinedAt(0)
^Compilation Failed
What is the right way to preserve PartialFunction functionality when going from PartialFunction to partially applied function?
You can use compose to preserve the partial nature:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = divide.compose {
case y: Int => (42, y)
}
divide42.isDefinedAt(0) // false
What you wrote doesn't work because it's actually syntactic sugar for the following:
val divide42 = new Function1[Int, Int] {
def apply(y: Int) = divide((42, y))
}
The call to divide inside divide42 is an expression that evaluates to Int (or throw). There is no way to preserve the fact that divide is a partial function with this syntax.
Or explicitly write a new partial function like this but more verbose:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = {
case (y: Int) if divide.isDefinedAt((42, y)) => divide((42, y))
}
divide42.isDefinedAt(0) // false
Help the compiler help you, define your types explicitly:
EDIT: I realized that simply changing the types results in the y != 0 part of the function not working as intended. compose addresses this as already mentioned in another answer (which is correct).
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if y != 0 => x / y
}
// OLD: val divide42: PartialFunction[Int, Int] = (y: Int) => divide((42, y))
// |- Returns true for `isDefinedAt(0)` which is WRONG!!
// |- If someone could explain why this happens (???), please comment :)
val divide42: PartialFunction[Int, Int] = (y: Int) => divide.compose {
case y: Int => (42, y)
}
divide42.isDefinedAt(0) // False
When you define it as you have, the compiler changes the type of divide42 to Int => Int as opposed to PartialFunction[Int, Int]:
// Implicit type, `Int => Int`
val divide42 = (y: Int) => divide((42, y))
// `isDefinedAt` is not defined for `Int => Int`
divide42.isDefinedAt(0) // !! Error !!
The following seem right to me:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = {
case x if (x != 0) => divide(42, x)
}
divide42.isDefinedAt(0) // false
divide42(6) // 7
This both follows the correct definition pattern for PartialFunction and suits the definition of a partially applied function
I'm reading the FP for Mortals book which has following line:
There can only be one implementation of a typeclass for any given type parameter, a property known as typeclass coherence. Typeclasses look superficially similar to algebraic interfaces from the previous chapter, but algebras do not have to be coherent.
I do not understand this paragraph fully. Suppose we have following typeclass:
trait Ordering[T] {
def compare(x: T, y: T): Int
}
I can create two implementations for the Int type like this:
val ord1: Ordering[Int] = new Ordering[Int] {
def compare(x: Int, y: Int): Int =
if (x > y) 1 else if (x == y) 0 else -1
}
val ord2: Ordering[Int] = new Ordering[Int] {
def compare(x: Int, y: Int): Int =
if (x > y) -1 else if (x == y) 0 else 1
}
What do authors mean when they say that typeclass can have only one implementation? It doesn't apply for instances of the typeclass as we can have multiple ones for the same type. To what it is applied? Also why ADTs are not coherent in that sense?
Instances of a type class are defined as implicits.
implicit val ord1: Ordering[Int] = new Ordering[Int] {
def compare(x: Int, y: Int): Int =
if (x > y) 1 else if (x == y) 0 else -1
}
implicit val ord2: Ordering[Int] = new Ordering[Int] {
def compare(x: Int, y: Int): Int =
if (x > y) -1 else if (x == y) 0 else 1
}
If you ask implicitly[Ordering[Int]] you'll have
Error: ambiguous implicit values:
both value ord1 in object App of type => App.Ordering[Int]
and value ord2 in object App of type => App.Ordering[Int]
match expected type App.Ordering[Int]
I have a function that I would like it to be generic but restrict it to take a certain subtypes. To keep things simple, I want my function to just work on Long, Int, Float and Double. So here is what I have come up with:
def covariance[A](xElems: Seq[A], yElems: Seq[A]): A = {
val (meanX, meanY) = (mean(xElems), mean(yElems))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xElems), meanDiff(meanY, yElems))
((meanDiffX zip meanDiffY).map { case (x, y) => x * y }.sum) / xElems.size - 1
}
def mean[A](elems: Seq[A]): A = {
(elems.fold(_ + _)) / elems.length
}
def meanDiff[A](mean: A, elems: Seq[A]) = {
elems.map(elem => elem - mean)
}
Here is the method that I will use to check for the above mentioned types:
import scala.reflect.{ClassTag, classTag}
def matchList2[A : ClassTag](list: List[A]) = list match {
case intlist: List[Int #unchecked] if classTag[A] == classTag[Int] => println("A List of ints!")
case longlist: List[Long #unchecked] if classTag[A] == classTag[Long] => println("A list of longs!")
}
Notice that I'm using ClassTag. I can also use a TypeTag and perhaps even the Shapeless library.
I would like to know if this is a good approach? Or should I use bounded types to solve what I want?
EDIT: Based on the comment and suggestion to use the Fractional Typeclass, here is how I think it could work!
def covariance[A: Fractional](xElems: Seq[A], yElems: Seq[A]): A = {
val (meanX, meanY) = (mean(xElems), mean(yElems))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xElems), meanDiff(meanY, yElems))
((meanDiffX zip meanDiffY).map { case (x, y) => x * y }.sum) / xElems.size - 1
}
def mean[A](elems: Seq[A]): A = {
(elems.fold(_ + _)) / elems.length
}
def meanDiff[A](mean: A, elems: Seq[A]) = {
elems.map(elem => elem - mean)
}
Based on the comments and inputs, here is what I came up with!
def mean[A](xs: Seq[A])(implicit A: Fractional[A]): A =
A.div(xs.sum, A.fromInt(xs.size))
def covariance[A](xs: Seq[A], ys: Seq[A])(implicit A: Fractional[A]): A = {
val (meanX, meanY) = (mean(xs), mean(ys))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xs), meanDiff(meanY, ys))
(meanDiffX zip meanDiffY).map { case (x, y) => A.div(A.times(x, y), A.fromInt(xs.size - 1)) }.sum
}
def meanDiff[A](mean: A, elems: Seq[A])(implicit A: Fractional[A]): Seq[A] = {
elems.map(elem => A.minus(elem, mean))
}
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)
I want IMPLICIT args in a higher order function, like:
func(arg1) { implicit (x, y) => x * y }
But the compiler says:
error: expected start of definition
val a = func("2", "4") { implicit (x, y) =>
^
java version "1.7.0_40"
Scala code runner version 2.10.2-RC2 -- Copyright 2002-2013, LAMP/EPFL
The runnable sample code:
object Test extends App {
new Test().run
}
class Test {
def run = {
val a = func("2", "4") { (x, y) => // It's OK
x * y
}
println("a: " + a)
val b = gunc("2", "4") { implicit x => { implicit y => // It's OK
x * y
}}
println("b: " + b)
}
def func(x: String, y: String)(f: (Int, Int) => Int) = f(x.toInt, y.toInt)
def gunc(x: String, y: String)(g: Int => Int => Int) = g(x.toInt)(y.toInt)
def hunc(x: String, y: String)(h: Tuple2[Int, Int] => Int) = h((x.toInt, y.toInt))
}
[ADD COMMENT]
I wonder...
We can declare as "implicit x => ..." with one arg.
It seems there is no way to declare two implicit args.
Try adding:
val c = hunc("2", "4") { implicit pair => pair._1 * pair._2 }
When you say implicit y => y * 2 you're not
declaring an implicit argument but mark the function as implicit,
so you make an analog to this:
implicit val f1 = (y: Int) => y * 2
def func1(x: String, y: String)(f: Int => Int) = f(1)
func1("", "")(f1)
When you want to mark a function with two
arguments as implicit you can do it this way:
implicit val f2 = (x: Int, y: Int) => y * 2
def func2(x: String, y: String)(f: (Int, Int) => Int) = f(1, 2)
func2("", "")(f2)
But you cannot do it so:
func2("", "")(implicit (x, y) => x), in this particular case I just don't see any meaning to use implicits.
Also you can see this question, maybe you'll find some useful information there