λ
GET /endpoint?number=5
10
def addFiveAction(
params: Map[String, String]
) = {
val nbS = params("number")
if(nbS != "") {
val nb = nbS.toInt
nb + 5
} else {
0
}
}
addFiveAction(Map("number" -> "12"));
// 17
addFiveAction(Map("yolo" -> "12"));
// java.lang.NullPointerException
addFiveAction(Map("number" -> "yolo"));
// java.lang.NumberFormatException
def addFiveAction(
params: Map[String, String]) = {
val nbS = params("number")
if(nbS != null) {
if(!nbS != "") {
try {
val nb = nbS.toInt
nb + 5
} catch {
case e: NumberFormatException e => 0
}
}
} else {
0
}
}
GET /endpoint?n1=20&n2=22
42
def addNumbersAction(
params: Map[String, String]) = {
val nbS1 = params("n1");
val nbS2 = params("n2");
if(nbS1 != null) {
if(!nbS1 != "") {
try {
val nb1 = nbS1.toInt
if(nbS2 != null) {
if(!nbS2 != "") {
try {
val nb2 = nbS2.toInt
nbS1 + nbS2
} catch {
case e: NumberFormatException => 0
}
}
}
} catch {
case e: NumberFormatException => 0
}
}
} else {
0
}
}
def getKeyAt(
values: Map[String, String],
key: String
): MaybeString
def parseInt(
string: String
): MaybeInt
def parseInt(str: String):
Option[Int]
map[A,B]#get(key: A): Option[B]
def getInt(
index: String,
vals: Map[String, String]
): Option[Int]
def addNumbersAction(
params: Map[String, String]
): Int = {
val i1 = getInt("n1", params)
val i2 = getInt("n2", params)
i1.getOrElse(0) + i2.getOrElse(0)
}
def addNumbersAction(
params: Map[String, String]) = {
val nbS1 = params("n1");
val nbS2 = params("n2");
if(nbS1 != null) {
if(!nbS1 != "") {
try {
val nb1 = nbS1.toInt
if(nbS2 != null) {
if(!nbS2 != "") {
try {
val nb2 = nbS2.toInt
nbS1 + nbS2
} catch {
case e: NumberFormatException => 0
}
}
}
} catch {
case e: NumberFormatException => 0
}
}
} else {
0
}
}
∃
« there exists »
Int -> Int
String -> String
∀
« for all »
val myValue = if(expression) {
"if true"
} else {
"if false"
}
val myValue =
for(x <- xs)
yield x*x
sealed trait Meter
sealed trait Mile
type RegularLength = Int @@ Meter
type ImperialGobbledygook = Int @@ Mile
val marsProbeAltitude: RegularLength = …
def f[A](x: A): A
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C)
def rev[A](xs: List[A]): List[A]
rev(Nil)
==
Nil
x in rev(a) => x in a
trait List[A] {
def filter(p: A => Boolean): List[A]
def map[B](f: A => B): List[B]
}
l.filter(compose(p,f)).map(f) ==
l.map(f).filter(p)
null
snull
can inhabit any typenull
can prove any propertydef f[A](x: A): String
def f[A](x: A): String =
x match {
case v: String => v
case v: Int => "int"
case _ => "whatever"
}
def f[A](x: A): String =
x.toString
def f[A](x: A): String = {
launchBallisticMissile()
System.getenv("JAVA_HOME")
}
def myMethod(a: Input): Output = ???
def myOtherMethod(
a: List[Input]
): List[Output] = {
a.map(myMethod)
}
case object Hole
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C) = Hole
Hole: A => C
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C) = (x: A) => Hole
x: A
Hole: C
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C) = (x: A) => g(Hole)
X: A
Hole: B
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C) = (x: A) => g(f(Hole))
x: A
Hole: A
Hole = x
def compose[A,B,C](
g: (B => C),
f: (A => B)
): (A => C) = (x: A) => g(f(x))
def fmap[A,B](
f: (A => B),
xs: List[A]
): List[B] = Hole
Hole: List[B]
def fmap[A,B](
f: (A => B),
xs: List[A]
): List[B] = xs match {
case Nil => Nil
case (head :: tail) =>
Hole1 :: Hole2
}
head: A, tail: List[A]
Hole1: B, Hole2: List[B]
def fmap[A,B](
f: (A => B),
xs: List[A]
): List[B] = xs match {
case Nil => Nil
case (head :: tail) =>
f(head) :: fmap(f, tail)
}
a -> a
Int -> Int
a -> b -> a
(a, b) -> a
a -> (b -> a)
(Ord a) =>
[a] -> [a]
Eq a =>
[a] -> [a]
[Maybe a] ->
Maybe [a]
def reverse[A](
xs: List[A]
): List[A]
def reverseProp[A: Equal](
xs: List[A],
ys: List[A]
) = {
reverse(xs ++ ys) ==
reverse(ys) ++ reverse(xs)
}
Types then
Property-based tests then
Unit tests
Try Idris