Abstract
Numeric programming is a notoriously difficult topic. For number crunching, e.g. solving systems of linear equations, we need raw performance.
However, using floating-point numbers may lead to inaccurate results. On top of that, as functional programmers, we’d really like to abstract over concrete number types, which is where abstract algebra comes into play.
This interplay between abstract and concrete, and the fact that everything needs to run on finite hardware, is what makes good library support necessary for writing fast & correct programs.
Spire is such a library in the Typelevel Scala ecosystem.
This talk is an introduction to Spire, showcasing the ‘number tower’, real-ish numbers and how to obey the law.
Slides
Recording
Events
- J On The Beach, Marbella, Spain, May 16th, 2019
- Scala Hamburg, Hamburg, Germany, May 2nd, 2019
- Kraków Scala User Group, Kraków, Poland, February 21st, 2019
- Scala Romandie, Lausanne, Switzerland, December 18th, 2018
- Scala Italy, Florence, Italy, September 14th, 2018
- Munich Scala User Group, Munich, Germany, June 13th, 2018
- LX Scala, Lisbon, Portugal, June 8th, 2018
- Scala Portugal, Lisbon, Portugal, June 25th, 2016
Interview at J On The Beach
Testimonials
Trains are monoids and now I finally understand better my commuting issues: that's the "zero train"! @ScalaItaly pic.twitter.com/FpQKXWdZcG
— Carlo Micieli (@ChuckMiskyes) September 14, 2018
If you liked @larsr_h's talk, put a `SemiRing` on it. Crystal clear intro to numeric programming with Spire/Cats/Algebra. Kudos! pic.twitter.com/pe4y6yete9
— Stefano Baghino (@stefanobaghino) September 14, 2018
Demo code
All code snippets are tested with version 0.15.0 and assume the following imports:
import spire._
import spire.algebra._
import spire.math._
import spire.implicits._
import spire.laws._
import spire.syntax.literals._
import org.scalacheck._
Maps
val cities1 = Map("Portugal" -> List("Lisbon"), "Spain" -> List("Madrid"))
val cities2 = Map("Portugal" -> List("Coimbra"))
cities1 |+| cities2
Laws
RingLaws[Int].ring.all.check()
RingLaws[Float].ring.all.check()
Monoids
val score = r"5/7"
def twice[A : AdditiveMonoid](a: A) = a + a
twice(score)
twice(3)
twice(Map("Score" -> score))
score.toBigDecimal()
Reals
Real.pi
Real.pi.doubleValue()
Real.pi.toRational(1).toBigDecimal()
Real.pi.toRational(2).toBigDecimal()
Real.pi.toRational(4).toBigDecimal()
Rationals and Intervals
val score = r"5/7"
val confidence = score ± r"1/7"
confidence.intersects(r"3/4" ± r"1/8")
confidence.intersect(r"3/4" ± r"1/8")