Rounding through type ascription - scala

I would like to introduce a custom class, say Decimal2, so that I would be able to round through type ascription:
val x: Decimal2 = 1.2345
// 1.24
So far I've tried this:
class Decimal2(val value: Double)
object Decimal2 {
def apply(value: Double) =
BigDecimal(value).
setScale(2, BigDecimal.RoundingMode.HALF_UP).
toDouble
implicit def doubleToDecimal2(x: Double) = Decimal2(x)
}
val a: Decimal2 = 1.2345
But:
the last line apparently fails.
return type of apply method is Double, not Decimal2
How can I reach my goal?

One way is by explicitly creating a new instance of Decimal2 from apply method.
object Decimal2 {
def apply(value: Double): Decimal2 =
new Decimal2(BigDecimal(value)
.setScale(2, BigDecimal.RoundingMode.HALF_UP)
.toDouble)
implicit def doubleToDecimal2(x: Double): Decimal2 = Decimal2(x)
}
Another option is to tag the type:
trait RoundTo2
type Decimal2 = Double with RoundTo2
object Decimal2 {
def apply(value: Double): Decimal2 = {
BigDecimal(value)
.setScale(2, BigDecimal.RoundingMode.HALF_UP)
.toDouble
}.asInstanceOf[Double with RoundTo2]
}
implicit def doubleToDecimal2(x: Double): Decimal2 = Decimal2(x)
val a: Decimal2 = 1.2345

It's easy to do this with scala 3 opaque type.
I would say even more, opaque type is made for this kind of thing.
// a Decimal2 is a Double with some restriction
opaque type Decimal2 = Double
object Decimal2 :
def apply(d2 : Double) : Decimal2 = BigDecimal(d2).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
// extension method to Decimal2 to have a back conversion to a full Double
extension (d2 : Decimal2)
def double : Double = d2
// implicit conversion for convenience
given doubleToDecimal2 : Conversion[Double, Decimal2] = Decimal2(_)
now you can use it like you want :
val d2 : Decimal2 = 1.23456 // 1.23
d2 // Decimal2
d2.double // double

It looks like you have two requirements.
Make Decimal2 class provides a method that returns a rounded Double value.
Convert Double value to Decimal2 class
Here is a straightforward approach.
case class Decimal2(value: Double){
def toDouble: Double = BigDecimal(value).
setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
}
implicit class DoubleImprovement(val x: Double){
def toDecimal2: Decimal2 = Decimal2(x)
}
println(1.2345.toDecimal2.toDouble)

Related

Genaric type parsing in Scala with default value

I am looking for a Generic functional way to convert between Scala String to any numeric type. I need in case of failure to pass a default value.
For example, I need to convert from String to Int but in case the String to Int conversion failed. I need to pass a default value without having throws java.lang.NumberFormatException. I tried this way but doesn't get my idea as I need it generic and also with default value in case of exception
Edit: I updated the solution to parse from any type to any type. This makes the solution more generic based on the question requested. I think you can use Scala functional way to have the generic type [T] but you need to split it into two parts.
First to implement parse types which parses from any type [U] to
any type [T]. parseTypes takes a function canBuildFrom as a parameter using Scala functional way. Then based on the output of this function you will checks if it parsed correctly or it has an exception. Also, in case it failed to parse you can pass a default parameter.
def parseTypes[T,U](str: U, canBuildFrom: U ⇒ T): Either[java.lang.NumberFormatException, T] =
Try(canBuildFrom(str)).map(Right(_)).getOrElse {
Left(new java.lang.NumberFormatException(str.toString))
}
def safeParse[T,U](attributeValue: U, canBuildFrom: U ⇒ T, defaultValue: T): T = {
parseTypes(attributeValue, canBuildFrom) match {
case Right(x) ⇒ x
case Left(x) ⇒ defaultValue
case _ ⇒ defaultValue
}
}
def safeParseDoubleToBigDecimal(attributeValue: Double): BigDecimal = safeParse[BigDecimal,Double](attributeValue, toBigDecimal, 0.0)
You can use it to parse String to Int, Double, and Decimal as following:
def safeParseStringToInt(attributeValue: String): Int = safeParse[Int,String](attributeValue, _.toInt, 0)
def safeParseStringToDouble(attributeValue: String): Double = safeParse[Double ,String](attributeValue, _.toDouble, 0.0)
def safeParseStringToBigDecimal(attributeValue: String): BigDecimal = safeParse[BigDecimal ,String](attributeValue, BigDecimal(_), 0.0)
// example of usage
val x:Int = safeParseStringToInt("123",0)
val y:Int = safeParseStringToInt("aaa",0)
Update: I update this answer as I realized that #Dima's answer is somehow more functional and better than my answer I added the answer below copied from #Dima's answer as my answer marked as the correct answer.
trait ParseIt[T] {
protected def parse(s: String): T
def apply(s: String) = Try(parse(s)).toOption
}
implicit object ParseInt extends ParseIt[Int] {
protected def parse(s: String) = s.toInt
}
implicit object ParseDouble extends ParseIt[Double] {
protected def parse(s: String) = s.toDouble
}
// etc ...
def parse[T : ParseIt](s: String, orElse: => T) =
implicitly[ParseIt[T]](s).getOrElse(orElse)
val n: Int = parse("123", 0)
val d: Double = parse("123", 0.0)
This sort of thing is implemented really nice with typeclasses:
trait ParseIt[T] {
protected def parse(s: String): T
def apply(s: String) = Try(parse(s)).toOption
}
implicit object ParseInt extends ParseIt[Int] {
protected def parse(s: String) = s.toInt
}
implicit object ParseDouble extends ParseIt[Double] {
protected def parse(s: String) = s.toDouble
}
// etc ...
def parse[T : ParseIt](s: String, orElse: => T) =
implicitly[ParseIt[T]](s).getOrElse(orElse)
val n: Int = parse("123", 0)
val d: Double = parse("123", 0.0)

Requiring Scala implicit class in a function

My goal is to equip a variety of types (Timestamps, Dates, etc.) with nice properties they might not have by default (ordering, -, etc.). I'm doing something like this:
trait NiceProperties[T] {
def -(t: T): Double
def +(d: Double): T
...
}
implicit class BetterTimestamp(val t: Timestamp) extends NiceProperties[Timestamp] {
override def -(Timestamp): ...
}
This all works fine until I need to pass it into a function that assumes NiceProperties:
def myUtil[T](t: NiceProperties[T]): T = {
(t + 1.0) + 1.0
}
This now fails, because the function lacks the implicit evidence that the class T can be implicitly upcast to NiceProperties[T], so it can't add (t + 1.0): T to a double.
Is there a way to pass evidence for an implicit class into a function? Alternatively, is there a better pattern for this?
You could solve your issue by turning your NiceProperties[T] into a class that knows how to add, sum, ... two values of type T:
trait NiceProperties[T] {
def subtract(a: T, b: T): Double
def add(a: T, d: Double): T
}
You can now create an implicit NiceProperties object or val for Timestamps, Dates, ...
object BetterTimestamp extends NiceProperties[Timestamp] {
def subtract(a: Timestamp, b: Timestamp): Double = ???
def add(a: Timestamp, d: Double): Timestamp = ???
}
In your example method you'll request an implicit NiceProperties[T] which does the operations for your.
def myUtil[T](t: T)(implicit prop: NiceProperties[T]): T = {
prop.add(prop.add(t, 1.0), 1.0)
}
Since this is ugly, you can use an implicit class to add the +, -, ... operators to any class where an implicit NiceProperties[T] is available:
implicit class NicePropertiesOps[T](t: T)(implicit prop: NiceProperties[T]) {
def +(d: Double): T = prop.add(t, d)
def -(b: T): Double = prop.subtract(t, b)
}
Now your example from above should work almost as you described.
def myUtil[T : NiceProperties](t: T): T = {
(t + 1.0) + 1.0
}
https://scastie.scala-lang.org/0D1Y9sE5S5mrzm9coZPMWw
#Aki's answer is completely correct. Here is just an alternative approach of bringing the conversion into scope. This way is used in Numeric typeclass.
class Timestamp
trait NiceProperties[T] {
def subtract(a: T, b: T): Double
def add(a: T, d: Double): T
implicit class Ops(t:T) {
def +(d: Double): T = add(t, d)
def -(b: T): Double = subtract(t, b)
}
}
implicit object BetterTimestamp extends NiceProperties[Timestamp] {
def subtract(a: Timestamp, b: Timestamp): Double = ???
def add(a: Timestamp, d: Double): Timestamp = ???
}
def myUtil[T](t: T)(implicit prop: NiceProperties[T]): T = {
import prop._
(t + 1.0) + 1.0
}
and one more approach just of fun. This is how to avoid import:
trait NiceProperties[T] extends (T => Ops[T]) {
def subtract(a: T, b: T): Double
def add(a: T, d: Double): T
implicit val v = this
def apply(t:T) = new Ops(t)
}
class Ops[T](t:T)(implicit prop: NiceProperties[T]) {
def +(d: Double): T = prop.add(t, d)
def -(b: T): Double = prop.subtract(t, b)
}
implicit object BetterTimestamp extends NiceProperties[Timestamp] {
def subtract(a: Timestamp, b: Timestamp): Double = ???
def add(a: Timestamp, d: Double): Timestamp = ???
}
def myUtil[T:NiceProperties](t: T): T = {
(t + 1.0) + 1.0
}
The existing answers are good, but, in cases where you can't modify the trait, you can require the implicit conversion as a parameter:
def myUtil[T](t: T)(implicit conv: T => NiceProperties[T]) = t + 1.0 + 1.0
If you're doing this a lot, you might add an abstract type so you can use a context bound:
type HasNiceProperties[T] = T => NiceProperties[T]
def myUtil[T : HasNiceProperties](t: T) = t + 1.0 + 1.0

Implicit conversion not performed on Int

In Scala, I want to generate some aliases for basic types, and then implement conversions through a type class. This is both useful for me, and an opportunity to understand type classes. The code is the following:
type Index = Int
val Index = Int
type Integer = Int
val Integer = Int
type Real = Double
val Real = Double // to have companion object of Double also be the companion object of Real
trait Convertible[A] {
def toIndex(a: A): Index
def toInteger(a: A): Integer
def toReal(a: A): Real
}
implicit val ConvertibleIndex: Convertible[Index] = new Convertible[Index] {
def toIndex(i: Index) = i
def toInteger(i: Index) = i
def toReal(i: Index) = i.toDouble
}
implicit val ConvertibleInteger: Convertible[Integer] = new Convertible[Integer] {
def toIndex(i: Integer) = i
def toInteger(i: Integer) = i
def toReal(i: Integer) = i.toDouble
}
implicit val ConvertibleReal: Convertible[Real] = new Convertible[Real] {
def toIndex(r: Real) = r.toInt
def toInteger(r: Real) = r.toInt
def toReal(r: Real) = r
}
implicit val ConvertibleString: Convertible[String] = new Convertible[String] {
def toIndex(s: String) = s.toInt
def toInteger(s: String) = s.toInt
def toReal(s: String) = s.toDouble
}
implicit class ConvertibleSyntax[A](a: A)(implicit val c: Convertible[A]) {
def toIndex = c.toIndex(a)
def toInteger = c.toInteger(a)
def toReal = c.toReal(a)
}
Consider now:
val a = 3.toReal
val b = 3.0.toReal
val c = "3".toReal
The statement for a does not compile, with the compilation error: method toReal is not a member of Int. But, for the b and c statements, the implicit conversion to ConvertibleSyntax is properly done.
Why is the implicit conversion not working on Int, but is working on Double and String ?
Because you define ambiguous implicits for Index and Integer (both Int).
Which one should be chosen by compiler?
I think you might be a little confused about how Scala does implicit conversions. (A common mistake, as implicit is a little overused.)
I think that what you want, first of all, is an implicit conversion function - or even an implicit class. Here's how you could do this using the latter:
Note: Int, Index and Integer are treated identically, so are Real and Double, confusing matters somewhat, so I've pared this down to something that will work. Also, Convertible does not need to be generic as its conversion functions need no arguments. Finally, you shouldn't have both type and val declarations for your types.
type Index = Int
type Integer = Int
type Real = Double
trait Convertible {
def toIndex: Index
def toInteger: Integer
def toReal: Real
}
// Implicit classes cannot be defined in top-level scope, so they belong to an object.
object Implicits {
implicit class ConvertibleInt(i: Int)
extends Convertible {
override def toIndex = i
override def toInteger = i
override def toReal = i.toDouble
}
implicit class ConvertibleDouble(d: Double)
extends Convertible {
override def toIndex = d.toInt
override def toInteger = d.toInt
override def toReal = d
}
implicit class ConvertibleString(s: String)
extends Convertible {
override def toIndex = s.toInt
override def toInteger = s.toInt
override def toReal = s.toDouble
}
}
Now try this:
import Implicits._
val a = 3.toReal
val b = 3.0.toReal
val c = "3".toReal
What's happening here? Well, the implicit class declarations define classes that decorate the sole constructor argument with additional functions. If the compiler sees that you're trying to call a method on a type that doesn't have that method, it will look to see if there's an implicit conversion, in scope, to a type that does. If so, it is used and the function is called; if not, you get a compiler error. (The import statement is used to bring the classes into your current scope.)
So, for example, when the compiler sees "3".toReal it firstly determines that "3" is a String. Since this type doesn't have a .toReal member, it tries to find a conversion from a String to a type that does have such a member. It finds the ConvertibleString implicit class that takes a String argument and provides a .toReal method. Yay! So the compiler creates an instance of this class by passing "3" to ConvertibleString's constructor, then calls .toReal on the result.
On the other hand, when implicit is used with a value, it tells the compiler that the value is a default for any matching implicit arguments of the same type that are not provided. NEVER USE implicit WITH A PRIMITIVE OR COMMON LIBRARY TYPE!
For example:
final case class Example(i: Int)
// Default.
implicit val nameCanBeAnythingAtAll = Example(5)
// Function with implicit argument.
def someFunc(implicit x: Example): Unit = println(s"Value is $x")
Now, if you write something like this:
someFunc
the output will be Value is Example(5).
implicit values and arguments are an advanced topic, and I wouldn't worry about how they're used right now.

Could not find implicit value for parameter

I've recently started learning Scala's implicit "magic" and I'm having troubles with implicit Scala objects. I've tried all the possible variants but nothing seems to work.
Lets assume I have a class like this with some solve() function. It should return 2 Float values if the input a, b were Float. Otherwise it should return another type values:
class Solver[T](val a: T, val b: T) {
def solve[A](implicit num: customNumeric[T]): Option[(T, T)] = {
Option(
num.f(num.g(a)),
num.f(num.g(b)))
}
}
Let's assume another-type-value is an object of class like this:
class MyClass[T] (x: T, y: T)(implicit num: customNumeric[T]) {
val field : T = num.f(x)
}
And let's also assume that I dont have the functions I need in basic Scala Numeric so I should make my own custom numeric.
Here is what I've done:
I've made an abstract class for my own customNumeric with my methods f() and g() and couple of implicit objects that extend my customNumeric for some value types (Int, Float for example) and implemented method in them:
abstract class customNumeric[T] {
def f(x: T): T
def g(x: T): T
}
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = new MyClass[Int](x.field + 5)
def g(x: MyClass[Int]) = new MyClass[Int](x.field - 5)
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
}
In my opinion Solver's solve() should use implicit customNumeric object to get implementations for methods referenced inside solve() based upon type of the Solver's input values.
But this doesn't work as compiler says:
could not find implicit value for parameter num: customNumeric[Int]
def f...
It also complains because of not enough arguments for constructor MyClass at the same line.
I've already tried making companion object to cast Int to MyClass:
object Fraction {
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
}
But that also doen't seem to work. And I've tried to make another implicit object to implement methods I use in customNumeric[MyClass[Int]].
Do you have any ideas? Thanks in advance!
The problem is that you're trying to define the implicit objects with classes that themselves require that same implicit object.
Meaning, this:
class MyClass[T] (x: T, y: T)(implicit num: CustomNumeric[T])
Requires an existence of an implicit CustomNumeric[T]. You cannot define IntIsCustomNumeric using that type:
implicit object IntIsCustomNumeric extends customNumeric[MyClass[Int]]
When you implement IntIsCustomNumeric, you need to implement it for type Int, not for type MyClass[Int]. When you do that, i.e:
object CustomNumeric {
implicit object IntIsCustomNumeric extends CustomNumeric[Int] {
override def f(x: Int): Int = x
override def g(x: Int): Int = x
}
}
Now, you can create an Solver[Int] which takes an implicit CustomNumeric[Int]:
def main(args: Array[String]): Unit = {
import CustomNumeric._
val solver = new Solver[Int](1, 2)
println(solver.solve)
}
Now, it's also easier to create an implicit conversion from an Int type to something that creates a MyClass[Int]:
implicit object MyClassIsCustomNumeric extends CustomNumeric[MyClass[Int]] {
override def f(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 5)
override def g(x: MyClass[Int]): MyClass[Int] = new MyClass[Int](x.field + 3)
}
implicit def intToMyClass(i: Int) = new MyClass[Int](i)
What do you think about this
object customNumeric {
implicit object IntIsCustomNumeric extends customNumeric[Int] {
def f(x: Int): Int = x + 3
def g(x: Int): Int = x - 3
}
implicit object FloatIsCustomNumeric extends customNumeric[Float] {
def f(x: Float): Float = x + 3
def g(x: Float): Float = x - 3
}
implicit def int2MyClass(x: Int): MyClass[Int] = new MyClass[Int](x, 1)
implicit object cn extends customNumeric[MyClass[Int]] {
def f(x: MyClass[Int]) = x.field + 5
def g(x: MyClass[Int]) = x.field - 5
}
}

More advanced mathematics with Scala's Numeric and Fractional numbers

Recently I've (finally) started using Scala's Numeric trait, which does wonders. For example:
def square[A](x: A)(implicit num: Numeric[A]): A = num.times(x, x)
Now I can square any number be it Double, Integer, BigDecimal, or what not. Yet what if I want to do some more advanced math? For example, my logistic function for Double numbers looks like this:
def logisticFunction(x: Double): Double = 1.0 / (1.0 + math.exp(-x))
I could do the adding and dividing easily (I'd just have to use trait Fractional instead of Numeric), but what about the exponent? I sure don't want to write my own exp function (or any arbitrary function which takes Double arguments).
So, my question is this: how do I convert my A to Double, do my maths on that, and then convert back to A. Is it even possible?
EDIT:
That's how the signature of my function should look like:
def logisticFunction[A](x: A)(implicit num: Fractional[A]): A =
/* Magic happens here */
I've figured out the part about converting to double, which is as easy as num.toDouble(x). However the problem of converting back to A remains.
I still doubt this approach is really useful. But with your description, you will want something like this:
type FromDouble[A] = Double => A
type ToDouble [A] = A => Double
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
implicit def bigDecimalToDouble(b: BigDecimal) = b.toDouble
logisticFunction(BigDecimal(0.5))
Or with dedicated type class:
object FromDouble {
implicit object _Double extends FromDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends FromDouble[BigDecimal] {
def apply(d: Double) = BigDecimal(d)
}
}
trait FromDouble[A] extends (Double => A)
object ToDouble {
implicit object _Double extends ToDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends ToDouble[BigDecimal] {
def apply(b: BigDecimal) = b.toDouble
}
}
trait ToDouble[A] extends (A => Double)
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))
You will need a type class that provides trigonometric functions such as exp. Scala's standard library does not go beyond Fractional. You could try to use Spire.
Example:
$ sbt core/console
import spire.math._
import spire.algebra._
import spire.implicits._
def logisticFunction[A](x: A)(implicit m: Field[A], t: Trig[A]): A =
m.one / (m.one + exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))