More advanced mathematics with Scala's Numeric and Fractional numbers - scala

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))

Related

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.

Generic conversion to Numeric

I would like to write a generic conversion function converting a sequence of Doubles into any Numeric class, something along the lines of:
def construct[T : Numeric](a: Seq[Double]): Seq[T] = {
val n = implicitly[Numeric[T]]
a.map { value =>
value
???
}
}
The inverse is easy, using Numeric toDouble, but I did not find a way how to do this direction. How can that be done?
There is n.fromInt(value.toInt), but if you don't want to lose precision your are out of luck with scala.math.Numeric. I would suggest implementing your own type class:
trait Num[T] { def fromDouble(d: Double): T }
object Num { implicit val wateveryouneed = ... }
def construct[T](a: Seq[Double])(implicit n: Num[T]: Seq[T] =
a.map(n.fromDouble)

How to implement Ordered properly

I have a trait
trait Weight {
def getWeight: Int
}
Multiple classes inherits it, example:
case class Test(n: Int) extends Weight {
override def getWeight: Int = n
}
Now i want to add sorting ability to all Weight subclasses. I added Ordered to Weight:
trait Weight extends Ordered[Weight] {
def getWeight: Int
override def compare(that: Weight): Int = this.getWeight.compareTo(that.getWeight)
}
Try sorting:
val seq = Seq(Test(1), Test(4), Test(3), Test(2))
seq.sorted // error
And it's not compiles:
Error:(74, 6) diverging implicit expansion for type
scala.math.Ordering[A$A254.this.Test] starting with method $conforms
in object Predef seq.sorted;}
^
Whats i am doing wrong?
Another solution a bit different than mdm. Since sorted takes an implicit of Ordering, you can do the following:
seq.sorted(Ordering[Weight])
Your solution does not work because Ordered[T] is invariant in T, meaning that Ordered[Weight] has no relationship with Ordered[A]. You would need to specify that in the sub-classes.
You could use an implicit Ordering rather than an Ordered.
trait Weight{
def getWeight : Int
}
object Weight{
implicit def ordering[T <: Weight] : Ordering[T] = Ordering.by(w => w.getWeight)
}
case class A(w : Int) extends Weight{
def getWeight = w
}
case class B(w : Int) extends Weight{
def getWeight = w
}
import Weight._
Seq(A(1),B(2),B(0),A(3),A(-3)).sorted
Will result in:
List(A(-3), B(0), A(1), B(2), A(3))
Note that this solution relies on an Ordering[Int] to be available (which is, by default).

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
}
}

Scala, simple notation of Imaginary (number)

Imagine that I have the class Imaginary(x) and the class Real(y) in Scala. Is there a way to do ComplexNumber = 3 + 2i instead of doing ComplexNumber = Real(3) + Imaginary(2) ?
Thanks.
Is 3 + 2.i enough?
sealed trait ComplexNumber {
val re: Int
val im: Int
}
case class Real(re: Int) extends ComplexNumber { val im: Int = 0 }
implicit class ToReal(val re: Int) extends AnyVal {
def +(that: Imaginary) = Mixed(re, that.im)
}
case class Imaginary(im: Int) extends ComplexNumber { val re: Int = 0 }
implicit class ToImaginary(val im: Int) extends AnyVal {
def i: Imaginary = Imaginary(im)
}
case class Mixed(re: Int, im: Int) extends ComplexNumber
Usage:
scala> 3 + 2.i
res3: Mixed = Mixed(3,2)
2i means 2*i. You can't replace 2*a with 2a in scala so you should use operator *.
case class ComplexNumber(re: Int, im: Int){
def +(that: ComplexNumber) = ComplexNumber(re + that.re, im + that.im)
def -(that: ComplexNumber) = ComplexNumber(re - that.re, im - that.im)
def *(that: ComplexNumber) = ComplexNumber(re*that.re - im*that.im, re*that.im + im*that.re)
}
implicit def intToComplec(i: Int): ComplexNumber = ComplexNumber(i, 0)
object I extends ComplexNumber(0, 1)
Usage:
scala> 3 + 2*I
res0: ComplexNumber = ComplexNumber(3,2)
scala> 4 - I
res1: ComplexNumber = ComplexNumber(4,-1)
Be careful. Remember that the real and imaginary parts of a complex number have to both be real. Could you do something like:
case class Complex(real: Real, imag: Real) {
// in here define all your arithmetic ops
}
Then you could use senia's implicit trick to turn numbers automatically into reals and declare an i method in Real that would turn it into an imaginary number.
// inside Real
def i: Complex = Complex(Real(0), this)
I would just caution you not to complicate the code too much, just for the sake of cute syntax. Complex(a, b) is nice and clear. If you want to create a parser, feel free, but I'd reserve that for String values and let code be code.
No, this is not possible. The lexical analysis phase of the compiler "owns" suffixes on numeric strings such as f (Float), d (Double) and l (Long) and there is no extensibility for this notation.
You might want to think about using the new string interpolation mechanism to annotate constants. You'd have to accept parsing them and the "flag," if you will (your i), would have to be used in prefix position. That would give you something like this:
val imaginary = i"1.2+3.4i"
I'm not up-to-date with the capabilities of macros in the new compiler, but perhaps you could get the parsing done at compile time, which would preclude attempting to work with malformed values at run-time.
This approach (whether compile-time or run-time parsed) would be flexible (insofar as you can be as accommodating as you like in the accepted formats) but it clearly does not match the notation that people use in mathematical texts.