Does the Scala library provide any support for lifting a method of a given type to a function value?
For example, suppose I want to lift String.length. I can write
val f: String => Int = _.length
or
val f = { s: String => s.length }
However, this syntax is not always ideal (particularly in the midst of a larger expression). I think I'm looking for something that will enable expressions like
Lift[String](_.length)
Lift[Option[Int]].lift(_.filter)
and I have in mind something like this:
class Lift[T] {
def apply[R](f: T => R): T => R = f
def lift[A, R](f: (T) => (A) => R): (T, A) => R =
f(_)(_)
def lift[A1, A2, R](f: (T) => (A1, A2) => R): (T, A1, A2) => R =
f(_)(_,_)
// ... etc. ...
}
object Lift {
def apply[T] = new Lift[T]
}
Question 1: Does the standard library (or any library) provide something like this?
Question 2: If not, is it possible to write it in such a way that Option.filter can be lifted as above (rather than as Lift[Option[Int]].lift[Int => Boolean, Option[Int]](_.filter))? Without supplying the type parameters on the lift method I get the following error:
error: missing parameter type for expanded function ((x$1) => x$1.filter)
Lift[Option[Int]].lift(_.filter)
^
Update:
Apparently, the problem I'm running in to has something to do with the overloaded lift method. If I rename the overloads, I can lift Option.filter without all the extra type parameters.
What is the problem with
(_: String).length
(_: Option[Int]).filter _
?
I finally came up with a solution that I'm happy with. This version supports simple syntax and a single entry point to the API, while also providing control over the form of the lifted function (i.e. uncurried, partly curried, or fully curried).
Examples:
I'll use the following class definition in the examples below:
class Foo {
def m1: Int = 1
def m2(i: Int): Int = i
def m3(i: Int, j: Int): Int = i + j
}
The simplest form of lifting is to return the method as a partially applied function, equivalent to invoking ((_: Foo).method _):
scala> lift[Foo](_.m1) // NOTE: trailing _ not required
res0: (Foo) => Int = <function1>
scala> lift[Foo](_.m2 _) // NOTE: trailing _ required
res1: (Foo) => (Int) => Int = <function1>
scala> lift[Foo](_.m3 _)
res2: (Foo) => (Int, Int) => Int = <function1> // NOTE: the result is partly curried
By importing some implicits, one can request curried or uncurried forms:
scala> {
| import CurriedLiftables._
| lift[Foo](_.m3 _)
| }
res3: (Foo) => (Int) => (Int) => Int = <function1>
scala> {
| import UncurriedLiftables._
| lift[Foo](_.m3 _)
| }
res4: (Foo, Int, Int) => Int = <function3>
Implementation:
class Lift[T] {
def apply[R,F](f: T => R)(implicit e: (T => R) Liftable F): F = e.lift(f)
}
object lift {
def apply[T] = new Lift[T]
}
class Liftable[From, To](val lift: From => To)
class DefaultLiftables {
implicit def lift[F]: F Liftable F = new Liftable(identity)
}
object Liftable extends DefaultLiftables
class UncurriedLiftable1 extends DefaultLiftables {
implicit def lift1[T, A, R]: (T => A => R) Liftable ((T, A) => R) =
new Liftable( f => f(_)(_) )
}
class UncurriedLiftable2 extends UncurriedLiftable1 {
implicit def lift2[T, A1, A2, R]: (T => (A1, A2) => R) Liftable ((T, A1, A2) => R) =
new Liftable ( f => f(_)(_,_) )
}
// UncurriedLiftable3, UncurriedLiftable4, ...
object UncurriedLiftables extends UncurriedLiftable2
class CurriedLiftable2 extends DefaultLiftables {
implicit def lift2[T, A1, A2, R]: (T => (A1, A2) => R) Liftable (T => A1 => A2 => R) =
new Liftable( f => (x: T) => (a1: A1) => (a2: A2) => f(x)(a1, a2) )
}
// CurriedLiftable3, CurriedLiftable4, ...
object CurriedLiftables extends CurriedLiftable2
My previous solution required a separate lift method for each arity:
import Lift._
val f1 = lift0[String](_.length)
val f2 = lift1[Option[Int]](_.filter)
val f3 = lift2[Either[String, Int]](_.fold)
Implementation:
class Lift0[T] {
def apply[R](f: T => R): T => R = f
}
class Lift1[T] {
def apply[A, R](f: (T) => (A) => R): (T, A) => R =
f(_)(_)
}
class Lift2[T] {
def apply[A1, A2, R](f: (T) => (A1, A2) => R): (T, A1, A2) => R =
f(_)(_,_)
}
// ... etc. ...
object Lift {
def lift0[T] = new Lift0[T]
def lift1[T] = new Lift1[T]
def lift2[T] = new Lift2[T]
// ... etc. ...
}
Passing in filter as partially applied method seems to do the job:
scala> class Lift[T] {
| def apply[R](f: T => R): T => R = f
| }
defined class Lift
scala> object Lift {
| def apply[T] = new Lift[T]
| }
defined module Lift
scala> val ls = Lift[String](_.length)
ls: (String) => Int = <function1>
scala> val los = Lift[Option[Int]](_.filter _)
los: (Option[Int]) => ((Int) => Boolean) => Option[Int] = <function1>
Related
I'm trying to figure out how to abstract over a curried function.
I've can abstract over an uncurried function via:
def liftAU[F, P <: Product, L <: HList, R, A[_]](f: F)
(implicit
fp: FnToProduct.Aux[F, L => R],
gen: Generic.Aux[P, L],
ap: Applicative[A]
): A[P] => A[R] = p => p.map(gen.to).map(f.toProduct)
This will take a function like (Int, Int) => Int and turn it into something like Option[(Int, Int)] => Option[Int]. And it works for any arity of function.
I want to create the curried version which will take a function like Int => Int => Int and convert it to Option[Int] => Option[Int] => Option[Int].
It should also work for any arity of curried function.
Since FnToProduct only works on the first parameter list, it's not helpful here, I've also tried to write some recursive definitions at the typelevel, but I'm having issues defining the types.
Not really sure if its possible, but would love to know if others have tried anything like this.
Dmytro's answer doesn't actually work for me unless I change the instance names in one of the objects, and even then it doesn't work for a function like Int => Int => Int => Int, and I find working with Poly values really annoying, so instead of debugging the previous answer, I'm just going to write my own.
You can actually write this operation pretty nicely using a 100% Shapeless-free type class:
import cats.Applicative
trait LiftCurried[F[_], I, O] {
type Out
def apply(f: F[I => O]): F[I] => Out
}
object LiftCurried extends LowPriorityLiftCurried {
implicit def liftCurried1[F[_]: Applicative, I, I2, O2](implicit
lc: LiftCurried[F, I2, O2]
): Aux[F, I, I2 => O2, F[I2] => lc.Out] = new LiftCurried[F, I, I2 => O2] {
type Out = F[I2] => lc.Out
def apply(f: F[I => I2 => O2]): F[I] => F[I2] => lc.Out =
(Applicative[F].ap(f) _).andThen(lc(_))
}
}
trait LowPriorityLiftCurried {
type Aux[F[_], I, O, Out0] = LiftCurried[F, I, O] { type Out = Out0 }
implicit def liftCurried0[F[_]: Applicative, I, O]: Aux[F, I, O, F[O]] =
new LiftCurried[F, I, O] {
type Out = F[O]
def apply(f: F[I => O]): F[I] => F[O] = Applicative[F].ap(f) _
}
}
It's probably possible to make that a little cleaner but I find it reasonable readable as it is.
You might want to have something concrete like this:
def liftCurriedIntoOption[I, O](f: I => O)(implicit
lc: LiftCurried[Option, I, O]
): Option[I] => lc.Out = lc(Some(f))
And then we can demonstrate that it works with some functions like this:
val f: Int => Int => Int = x => y => x + y
val g: Int => Int => Int => Int = x => y => z => x + y * z
val h: Int => Int => Int => String => String = x => y => z => _ * (x + y * z)
And then:
scala> import cats.instances.option._
import cats.instances.option._
scala> val ff = liftCurriedIntoOption(f)
ff: Option[Int] => (Option[Int] => Option[Int]) = scala.Function1$$Lambda$1744/350671260#73d06630
scala> val gg = liftCurriedIntoOption(g)
gg: Option[Int] => (Option[Int] => (Option[Int] => Option[Int])) = scala.Function1$$Lambda$1744/350671260#2bb9b82c
scala> val hh = liftCurriedIntoOption(h)
hh: Option[Int] => (Option[Int] => (Option[Int] => (Option[String] => Option[String]))) = scala.Function1$$Lambda$1744/350671260#45eec9c6
We can also apply it a couple more times just for the hell of it:
scala> val hhhh = liftCurriedIntoOption(liftCurriedIntoOption(hh))
hhh: Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[String]]] => Option[Option[Option[String]]]))) = scala.Function1$$Lambda$1744/350671260#592593bd
So the types look okay, and for the values…
scala> ff(Some(1))(Some(2))
res0: Option[Int] = Some(3)
scala> ff(Some(1))(None)
res1: Option[Int] = None
scala> hh(Some(1))(None)(None)(None)
res2: Option[String] = None
scala> hh(Some(1))(Some(2))(Some(3))(Some("a"))
res3: Option[String] = Some(aaaaaaa)
…which I think is what you were aiming for.
You can define recursive Poly
object constNone extends Poly1 {
implicit def zeroCase[In]: Case.Aux[In, Option[Int]] = at(_ => None)
implicit def succCase[In, In1, Out](implicit
cse: Case.Aux[In, Out]): Case.Aux[In1, In => Out] = at(_ => cse(_))
}
object transform extends Poly1 {
implicit def zeroCase: Case.Aux[Int, Option[Int]] = at(Some(_))
implicit def succCase[In, Out](implicit
cse: Case.Aux[In, Out],
noneCase: constNone.Case.Aux[In, Out]
): Case.Aux[Int => In, Option[Int] => Out] =
at(f => {
case Some(n) => cse(f(n))
case None => noneCase(f(0))
})
}
(transform((x: Int) => (y: Int) => x + y) _)(Some(1))(Some(2)) //Some(3)
(transform((x: Int) => (y: Int) => x + y) _)(Some(1))(None) //None
(transform((x: Int) => (y: Int) => x + y) _)(None)(Some(2)) //None
The second argument of myFunc is a function with complex arguments:
def myFunc(list : List[String],
combine: (Map[String, ListBuffer[String]], String, String) => Unit) = {
// body of myFunc is just a stub and doesn't matter
val x = Map[String, ListBuffer[String]]()
list.foreach ((e:String) => {
val spl = e.split(" ")
combine(x, spl(0), spl(1))
})
x
}
I need to pass second argument to myFunc, so it can be used with various types A, B instead of specific String, ListBuffer[String].
def myFunc(list : List[A], combine: (Map[A, B], A, A) => Unit) = {
val x = Map[A, B]()
list.foreach(e => {
combine(x, e)
})
}
How to declare and call such construct?
You can do the following,
def myFunc[A, B](list : List[A], combine: (Map[A, B], A, A) => Unit) = {
val x = Map[A, B]()
list.foreach (e => combine(x, e, e))
x
}
Ad use it like
myFunc[String, Int](List("1","2","3"), (obj, k, v) => obj.put(k, v.toInt) )
It seems that you are looking to generalise the container being used. Were you looking for something like this? Here we import scala.language.higherKinds so that we can take Container, a kind which takes a single type parameter as a type parameter to addPair.
import scala.language.higherKinds
def addPair[K, V, Container[_]](map: Map[K, Container[V]],
addToContainer: (Container[V], V) => Container[V],
emptyContainer: => Container[V],
pair: (K, V)): Map[K, Container[V]] = {
val (key, value) = pair
val existingValues = map.getOrElse(key, emptyContainer)
val newValues = addToContainer(existingValues, value)
map + (key -> newValues)
}
Is it possible to do match-case over functions?
I want to define a behavior for different types of functions. Say I have the following possibilities:
f: T => Int
f: T => String
f: T => Lis[Int]
f: T => Boolean
f: T => Double
...
and for each of these options I have a function; for example for Int output:
def doThisForInt(f: T => Int) = { ... }
and this for Boolean output:
`
def doThisForBoolean(f: T => Boolean) = { ... }
So now suppose a function definition is given: val f = (input: T) => true. We should choose the corresponding case to f: T => Boolean.
Note that all these functions differ in the output type. Alternatively, given f can I get the output type of this function?
TypeTags are what you are looking for:
import scala.reflect.runtime.universe._
def doThisForInt(f: T => Int) = ???
def printType[R: TypeTag](f: T => R) = typeOf[R] match {
case t if t =:= typeOf[Int] =>
val toInt: (T) => Int = f.asInstanceOf[T => Int]
doThisForInt(toInt)
case t if t =:= typeOf[Double] =>
// ...
case t if t =:= typeOf[List[Int]] =>
// ...
}
printType((x: T) => 1) // int
printType((x: T) => 2.0) // double
printType((x: T) => List(2)) // list
As you can see, it is possible, but not very elegant and against good practices.
Chains of instanceOf checks can often be replaced with virtual methods (see the example) and the result type of function can possibly be a type parameter. It's hard to give more advice without knowing more context for your use case.
I've been playing around with shapeless for a bit now.
But, yesterday I got stuck when trying to compose tupled functions.
What I was looking into specifically is composing two unary functions f1: T => R and f2: R => U => S into f: TU => S where T is a TupleN and TU := (t1, ... , tn, u)
import shapeless.ops.tuple._
implicit class Composable[T <: Product, R](val f1: T => R) extends AnyVal{
def compose2[U, S](f2: R => U => S)(implicit p: Prepend[T, Tuple1[U]]): (p.Out => S) = {
// how to provide the two required implicits for Last[p.Out] and Init[p.Out]?
tu => f1.andThen(f2)(tu.init)(tu.last)
}
}
val f1: ((Int, Int)) => Int = x => x._1 * x._2
val f2: ((Int, Int, Int)) => Int = f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
What I've been struggling with is providing the implicit proof for the tuple operations last and init, so the above code won't compile!
From a logical perspective it feels trivial as result of Prepend, but I couldn't figure out a way. So any idea is welcome :)
Using shapeless's facilities to abstract over arity I got somehow closer:
import shapeless.ops.function.{FnFromProduct, FnToProduct}
import shapeless.{::, HList}
implicit class Composable[F](val f: F) extends AnyVal{
// the new param U is appended upfront
def compose2[I <: HList, R, U, S](f2: R => U => S)
(implicit ftp: FnToProduct.Aux[F, I => R], ffp: FnFromProduct[U :: I => S]): ffp.Out = {
ffp(list => f2.compose(ftp(f))(list.tail)(list.head))
}
}
val f1: (Int, Int) => Int = (x1,x2) => x1 * x2
val f2: (Int, Int, Int) => Int = f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
This works, but then again I was really looking for compose2 to work on unary tupled Function1s. Also, this results in f: (U, t1, ..., tn) => S rather than f: TU => S with TU := (t1, ... , tn, u).
As Miles says, this would be more convenient with an undo for Prepend, but since the length of the second part is fixed, an approach similar to the one in my other answer isn't too bad at all:
import shapeless.ops.tuple._
implicit class Composable[T <: Product, R](val f1: T => R) extends AnyVal {
def compose2[U, S, TU](f2: R => U => S)(implicit
p: Prepend.Aux[T, Tuple1[U], TU],
i: Init.Aux[TU, T],
l: Last.Aux[TU, U]
): (p.Out => S) =
tu => f1.andThen(f2)(i(tu))(l(tu))
}
And then:
scala> val f1: ((Int, Int)) => Int = x => x._1 * x._2
f1: ((Int, Int)) => Int = <function1>
scala> val f2: ((Int, Int, Int)) => Int =
| f1.compose2((y: Int) => (x3: Int) => x3 + y).apply _
f2: ((Int, Int, Int)) => Int = <function1>
scala> f2((2, 3, 4))
res1: Int = 10
The trick is adding the output of Prepend to the type parameter list for compose2—which will generally be inferred—and then using Prepend.Aux to make sure that it's inferred appropriately. You'll often find in Shapeless that you need to refer to the output type of a type class in other type class instances in the same implicit parameter list in this way, and the Aux type members make doing so a little more convenient.
i want to write a memoize function in scala that can be applied to any function object no matter what that function object is. i want to do so in a way that lets me use a single implementation of memoize. i'm flexible about the syntax, but ideally the memoize appears somewhere very close to the declaration of the function as opposed to after the function. i'd also like to avoid first declaring the original function and then a second declaration for the memoized version.
so some ideal syntax might be this:
def slowFunction(<some args left intentionally vague>) = memoize {
// the original implementation of slow function
}
or even this would be acceptable:
def slowFUnction = memoize { <some args left intentionally vague> => {
// the original implementation of slow function
}}
i've seen ways to do this where memoize must be redefined for each arity function, but i want to avoid this approach. the reason is that i will need to implement dozens of functions similar to memoize (i.e. other decorators) and it's too much to ask to have to copy each one for each arity function.
one way to do memoize that does require you to repeat memoize declarations (so it's no good) is at What type to use to store an in-memory mutable data table in Scala?.
You can use a type-class approach to deal with the arity issue. You will still need to deal with each function arity you want to support, but not for every arity/decorator combination:
/**
* A type class that can tuple and untuple function types.
* #param [U] an untupled function type
* #param [T] a tupled function type
*/
sealed class Tupler[U, T](val tupled: U => T,
val untupled: T => U)
object Tupler {
implicit def function0[R]: Tupler[() => R, Unit => R] =
new Tupler((f: () => R) => (_: Unit) => f(),
(f: Unit => R) => () => f(()))
implicit def function1[T, R]: Tupler[T => R, T => R] =
new Tupler(identity, identity)
implicit def function2[T1, T2, R]: Tupler[(T1, T2) => R, ((T1, T2)) => R] =
new Tupler(_.tupled, Function.untupled[T1, T2, R])
// ... more tuplers
}
You can then implement the decorator as follows:
/**
* A memoized unary function.
*
* #param f A unary function to memoize
* #param [T] the argument type
* #param [R] the return type
*/
class Memoize1[-T, +R](f: T => R) extends (T => R) {
// memoization implementation
}
object Memoize {
/**
* Memoize a function.
*
* #param f the function to memoize
*/
def memoize[T, R, F](f: F)(implicit e: Tupler[F, T => R]): F =
e.untupled(new Memoize1(e.tupled(f)))
}
Your "ideal" syntax won't work because the compiler would assume that the block passed into memoize is a 0-argument lexical closure. You can, however, use your latter syntax:
// edit: this was originally (and incorrectly) a def
lazy val slowFn = memoize { (n: Int) =>
// compute the prime decomposition of n
}
Edit:
To eliminate a lot of the boilerplate for defining new decorators, you can create a trait:
trait FunctionDecorator {
final def apply[T, R, F](f: F)(implicit e: Tupler[F, T => R]): F =
e.untupled(decorate(e.tupled(f)))
protected def decorate[T, R](f: T => R): T => R
}
This allows you to redefine the Memoize decorator as
object Memoize extends FunctionDecorator {
/**
* Memoize a function.
*
* #param f the function to memoize
*/
protected def decorate[T, R](f: T => R) = new Memoize1(f)
}
Rather than invoking a memoize method on the Memoize object, you apply the Memoize object directly:
// edit: this was originally (and incorrectly) a def
lazy val slowFn = Memoize(primeDecomposition _)
or
lazy val slowFn = Memoize { (n: Int) =>
// compute the prime decomposition of n
}
Library
Use Scalaz's scalaz.Memo
Manual
Below is a solution similar to Aaron Novstrup's answer and this blog, except with some corrections/improvements, brevity and easier for peoples copy and paste needs :)
import scala.Predef._
class Memoized[-T, +R](f: T => R) extends (T => R) {
import scala.collection.mutable
private[this] val vals = mutable.Map.empty[T, R]
def apply(x: T): R = vals.getOrElse(x, {
val y = f(x)
vals += ((x, y))
y
})
}
// TODO Use macros
// See si9n.com/treehugger/
// http://stackoverflow.com/questions/11400705/code-generation-with-scala
object Tupler {
implicit def t0t[R]: (() => R) => (Unit) => R = (f: () => R) => (_: Unit) => f()
implicit def t1t[T, R]: ((T) => R) => (T) => R = identity
implicit def t2t[T1, T2, R]: ((T1, T2) => R) => ((T1, T2)) => R = (_: (T1, T2) => R).tupled
implicit def t3t[T1, T2, T3, R]: ((T1, T2, T3) => R) => ((T1, T2, T3)) => R = (_: (T1, T2, T3) => R).tupled
implicit def t0u[R]: ((Unit) => R) => () => R = (f: Unit => R) => () => f(())
implicit def t1u[T, R]: ((T) => R) => (T) => R = identity
implicit def t2u[T1, T2, R]: (((T1, T2)) => R) => ((T1, T2) => R) = Function.untupled[T1, T2, R]
implicit def t3u[T1, T2, T3, R]: (((T1, T2, T3)) => R) => ((T1, T2, T3) => R) = Function.untupled[T1, T2, T3, R]
}
object Memoize {
final def apply[T, R, F](f: F)(implicit tupled: F => (T => R), untupled: (T => R) => F): F =
untupled(new Memoized(tupled(f)))
//I haven't yet made the implicit tupling magic for this yet
def recursive[T, R](f: (T, T => R) => R) = {
var yf: T => R = null
yf = Memoize(f(_, yf))
yf
}
}
object ExampleMemoize extends App {
val facMemoizable: (BigInt, BigInt => BigInt) => BigInt = (n: BigInt, f: BigInt => BigInt) => {
if (n == 0) 1
else n * f(n - 1)
}
val facMemoized = Memoize1.recursive(facMemoizable)
override def main(args: Array[String]) {
def myMethod(s: Int, i: Int, d: Double): Double = {
println("myMethod ran")
s + i + d
}
val myMethodMemoizedFunction: (Int, Int, Double) => Double = Memoize(myMethod _)
def myMethodMemoized(s: Int, i: Int, d: Double): Double = myMethodMemoizedFunction(s, i, d)
println("myMemoizedMethod(10, 5, 2.2) = " + myMethodMemoized(10, 5, 2.2))
println("myMemoizedMethod(10, 5, 2.2) = " + myMethodMemoized(10, 5, 2.2))
println("myMemoizedMethod(5, 5, 2.2) = " + myMethodMemoized(5, 5, 2.2))
println("myMemoizedMethod(5, 5, 2.2) = " + myMethodMemoized(5, 5, 2.2))
val myFunctionMemoized: (Int, Int, Double) => Double = Memoize((s: Int, i: Int, d: Double) => {
println("myFunction ran")
s * i + d + 3
})
println("myFunctionMemoized(10, 5, 2.2) = " + myFunctionMemoized(10, 5, 2.2))
println("myFunctionMemoized(10, 5, 2.2) = " + myFunctionMemoized(10, 5, 2.2))
println("myFunctionMemoized(7, 6, 3.2) = " + myFunctionMemoized(7, 6, 3.2))
println("myFunctionMemoized(7, 6, 3.2) = " + myFunctionMemoized(7, 6, 3.2))
}
}
When you run ExampleMemoize you will get:
myMethod ran
myMemoizedMethod(10, 5, 2.2) = 17.2
myMemoizedMethod(10, 5, 2.2) = 17.2
myMethod ran
myMemoizedMethod(5, 5, 2.2) = 12.2
myMemoizedMethod(5, 5, 2.2) = 12.2
myFunction ran
myFunctionMemoized(10, 5, 2.2) = 55.2
myFunctionMemoized(10, 5, 2.2) = 55.2
myFunction ran
myFunctionMemoized(7, 6, 3.2) = 48.2
myFunctionMemoized(7, 6, 3.2) = 48.2
I was thinking that you could do something like this and than use a DynamicProxy for the actual implementation.
def memo[T<:Product, R, F <: { def tupled: T => R }](f: F )(implicit m: Manifest[F]):F
The idea being that becuase functions lack a common super type we use a structural type to find anything that can be tupled (Function2-22, you still need to special case Function1).
I throw the Manifest in there so you can construct the DynamicProxy from the function trait that is F
Tupling should also help with the memoization as such as you simple put the tuple in a Map[T,R]
This works because K can be a tuple type so memo(x,y,z) { function of x, y, z } works:
import scala.collection.mutable
def memo[K,R](k: K)(f: => R)(implicit m: mutable.Map[K,R]) = m.getOrElseUpdate(k, f)
The implicit was the only way I could see to bring in the map cleanly:
implicit val fibMap = new mutable.HashMap[Int,Int]
def fib(x: Int): Int = memo(x) {
x match {
case 1 => 1
case 2 => 1
case n => fib(n - 2) + fib(n - 1)
}
}
It feels like it should be possible to somehow wrap up an automatic HashMap[K,R] so that you don't have to make fibMap (and re-describe the type) explicitly.