Scala - How to define map, where value depends on key? - scala

Is there a way to define a Map, where Map value depends on its key, like
Map(key -> f(key), key2 -> f(key2), ...).

You're looking at this the wrong way...
A Map[K,V] is also an instance of Partialfunction[K,V]. So change everywhere you're using your Map type (vals, method params, etc.) to be a PartialFunction.
Then you can just work with f directly, or supply a Map[K,V] as the instance wherever you don't have a simple algebraic relationship between keys and values.
e.g.
def methodUsingMapping(x: PartialFunction[Int,Boolean]) = ...
//then
val myMap = Map(1->true, 2->true, 3->false)
methodUsingMapping(myMap)
//or
val isEven = PartialFunction(n: Int => n % 2 == 0)
methodUsingMapping(isEven)
//or
//note: case statements in a block is the smart way
// to define a partial function
// In this version, the result isn't even defined for odd numbers
val isEven: PartialFunction[Int,Boolean] = {
case n: Int if n % 2 == 0 => true
}
methodUsingMapping(isEven)
You also might also want to consider using (K) => Option[V], in which case you can supply an instance of the type via the lift method, which maps inherit from PartialFunction
e.g.
def methodUsingMapping(x: (Int)=>Option[Boolean]) = ...
//then
val myMap = Map(1->true, 2->true, 3->false)
methodUsingMapping(myMap.lift)
//or
def isEven(n: Int) = Some(n % 2 == 0)
methodUsingMapping(isEven)
//or
def isEven(n: Int) = n % 2 == 0
methodUsingMapping(x => Some(isEven(x)))

Lets say you have your keys in a list like this, and you want to convert it map with squares as values.
scala> val keyList = ( 1 to 10 ).toList
keyList: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val doSquare = ( x: Int ) => x * x
doSquare: Int => Int = <function1>
// Convert it to the list of tuples - ( key, doSquare( key ) )
scala> val tupleList = keyList.map( key => ( key, doSquare( key ) ) )
tuple: List[(Int, Int)] = List((1,1), (2,4), (3,9), (4,16), (5,25), (6,36), (7,49), (8,64), (9,81), (10,100))
val keyMap = tuple.toMap
keyMap: scala.collection.immutable.Map[Int,Int] = Map(5 -> 25, 10 -> 100, 1 -> 1, 6 -> 36, 9 -> 81, 2 -> 4, 7 -> 49, 3 -> 9, 8 -> 64, 4 -> 16)
Or to do it in one line
( 1 to 10 ).toList.map( x => ( x, x * x ) ).toMap
Or... if you have just few keys... then you can write the specific code
Map( 1 -> doSquare( 1 ), 2 -> doSquare( 2 ) )

Because you only need to define 4 methods to make a Map trait implementation, you could just roll your own:
trait MapWithRelationship[K, +V] extends Map[K, V] {
self =>
def pred: (K, Any) => Boolean
def underlying: Map[K, V]
def get(key: K): Option[V] = underlying.get(key)
def iterator: Iterator[(K, V)] = underlying.iterator
def + [V1 >: V](kv: (K, V1)): MapWithRelationship[K, V1] = {
val (k, v) = kv
if (pred(k, v)) {
new MapWithRelationship[K, V1] {
val pred = self.pred
val underlying = self.underlying + kv
}
} else {
throw new Exception(s"Key-value pair $kv failed MapWithRelationship predicate")
}
}
def -(key: K): MapWithRelationship[K, V] =
new MapWithRelationship[K, V] {
val pred = self.pred
val underlying = self.underlying - key
}
}
object MapWithRelationship {
def apply[K, V](rule: (K, Any) => Boolean)(pairs: (K, V)*) = {
val empty = new MapWithRelationship[K, V] {
def pred = rule
def underlying = Map.empty[K, V]
}
pairs.foldLeft(empty)(_ + _)
}
}
Then you can use as such:
scala> val x = MapWithRelationship[Int, Int]((k, v) => v == k * k)()
x: MapWithRelationship[Int,Int] = Map()
scala> val x2 = x + (1 -> 1)
x2: MapWithRelationship[Int,Int] = Map(1 -> 1)
scala> val x3 = x + (5 -> 25)
x3: MapWithRelationship[Int,Int] = Map(5 -> 25)
scala> val x4 = x + (6 -> "foo")
java.lang.Exception: Key-value pair (6,foo) failed MapWithRelationship predicate
at MapWithRelationship$class.$plus(<console>:21)
at MapWithRelationship$$anon$3.$plus(<console>:33)
... 32 elided

You could make an infinite map of squares using:
val mySquareMap = Map.empty[Int, Int].withDefault(d => d * d)
This map will still have +, get, iterator and other methods that won't work as desired, but if you need a read-only map that returns squares, this would work.
Of course, it would be more efficient and probably clearer to just use:
val mySquare = (d:Int) => d * d
as a function. However, the above Map might be useful if you need to use some API that requires that type.
To have a more full-fledged solution for this, you might be better off building your own class that extends Map[Int, Int] that overrides get to return the square of its argument.

Related

What is the efficient way to remove subsets from a List[List[String]]?

I have a ListBuffer of List[String], val tList = ListBuffer[TCount] where TCount is case class TCount(l: List[String], c: Long). I want to find those list l from tList which are not the subset of any other element of tlist and their c value is less than their superset c value. The following program works but I have to use two for loop that makes the code inefficient. Is there any better approach I can use to make the code efficient?
val _arr = tList.toArray
for (i <- 0 to (_arr.length - 1)) {
val il = _arr(i).l.toSet
val ic = _arr(i).c
for (j <- 0 to (_arr.length - 1)) {
val jl = _arr(j).toSet
val jc = _arr(j).c
if (i != j && il.subsetOf(jl) && ic >= jc) {
tList.-=(_arr(i))
}
}
}
Inspired by the set-trie comment:
import scala.collection.SortedMap
class SetTrie[A](val flag: Boolean, val children: SortedMap[A, SetTrie[A]])(implicit val ord: Ordering[A]) {
def insert(xs: List[A]): SetTrie[A] = xs match {
case Nil => new SetTrie(true, children)
case a :: rest => {
val current = children.getOrElse(a, new SetTrie[A](false, SortedMap.empty))
val inserted = current.insert(rest)
new SetTrie(flag, children + (a -> inserted))
}
}
def containsSuperset(xs: List[A], strict: Boolean): Boolean = xs match {
case Nil => !children.isEmpty || (!strict && flag)
case a :: rest => {
children.get(a).map(_.containsSuperset(rest, strict)).getOrElse(false) ||
children.takeWhile(x => ord.lt(x._1, a)).exists(_._2.containsSuperset(xs, false))
}
}
}
def removeSubsets[A : Ordering](xss: List[List[A]]): List[List[A]] = {
val sorted = xss.map(_.sorted)
val setTrie = sorted.foldLeft(new SetTrie[A](false, SortedMap.empty)) { case (st, xs) => st.insert(xs) }
sorted.filterNot(xs => setTrie.containsSuperset(xs, true))
}
Here is a method that relies on a data structure somewhat similar to Set-Trie, but which stores more subsets explicitly. It provides worse compression, but is faster during lookup:
def findMaximal(lists: List[List[String]]): List[List[String]] = {
import collection.mutable.HashMap
class Node(
var isSubset: Boolean = false,
val children: HashMap[String, Node] = HashMap.empty
) {
def insert(xs: List[String], isSubs: Boolean): Unit = if (xs.isEmpty) {
isSubset |= isSubs
} else {
var isSubsSubs = false || isSubs
for (h :: t <- xs.tails) {
children.getOrElseUpdate(h, new Node()).insert(t, isSubsSubs)
isSubsSubs = true
}
}
def isMaximal(xs: List[String]): Boolean = xs match {
case Nil => children.isEmpty && !isSubset
case h :: t => children(h).isMaximal(t)
}
override def toString: String = {
if (children.isEmpty) "#"
else children.flatMap{
case (k,v) => {
if (v.children.isEmpty) List(k)
else (k + ":") :: v.toString.split("\n").map(" " + _).toList
}
}.mkString("\n")
}
}
val listsWithSorted = for (x <- lists) yield (x, x.sorted)
val root = new Node()
for ((x, s) <- listsWithSorted) root.insert(s, false)
// println(root)
for ((x, s) <- listsWithSorted; if root.isMaximal(s)) yield x
}
Note that I'm allowed to do any kind of mutable nonsense inside the body of the method, because the mutable trie data structure never escapes the scope of the method, and can therefore not be inadvertently shared with another thread.
Here is an example with sets of characters (converted to lists of strings):
println(findMaximal(List(
"ab", "abc", "ac", "abd",
"ade", "efd", "adf", "bafd",
"abd", "fda", "dba", "dbe"
).map(_.toList.map(_.toString))))
The output is:
List(
List(a, b, c),
List(a, d, e),
List(e, f, d),
List(b, a, f, d),
List(d, b, e)
)
so indeed, the non-maximal elements ab, ac, abd, adf, fda and dba are eliminated.
And here is what my not-quite-set-trie data structure looks like (child nodes are indented):
e:
f
b:
e
d:
e
f
c
f
d:
e:
f
f
a:
e
b:
d:
f
c
f
d:
e
f
c
f
c
f
Not sure if you can avoid the complexity, but, I guess I'd write like this:
val tList = List(List(1, 2, 3), List(3, 2, 1), List(9, 4, 7), List(3, 5, 6), List(1, 5, 6), List(6, 1, 5))
val tSet = tList.map(_.toSet)
def result = tSet.filterNot { sub => tSet.count(_.subsetOf(sub)) > 1 }
Here's one approach:
Create an indexed Map for identifying the original List elements
Turn Map of List-elements into Map of Sets (with index)
Generate combinations of the Map elements and use a custom filter to capture the elements that are subset of others
Remove those subset elements from the Map of Sets and retrieve remaining elements from the Map of Lists via the index
Sample code:
type TupIntSet = Tuple2[Int, Set[Int]]
def subsetFilter(ls: List[TupIntSet]): List[TupIntSet] =
if ( ls.size != 2 ) List.empty[TupIntSet] else
if ( ls(0)._2 subsetOf ls(1)._2 ) List[TupIntSet]((ls(0)._1, ls(0)._2)) else
if ( ls(1)._2 subsetOf ls(0)._2 ) List[TupIntSet]((ls(1)._1, ls(1)._2)) else
List.empty[TupIntSet]
val tList = List(List(1,2), List(1,2,3), List(3,4,5), List(5,4,3), List(2,3,4), List(6,7))
val listMap = (Stream from 1).zip(tList).toMap
val setMap = listMap.map{ case (i, l) => (i, l.toSet) }
val tSubsets = setMap.toList.combinations(2).toSet.flatMap(subsetFilter)
val resultList = (setMap.toSet -- tSubsets).map(_._1).map(listMap.getOrElse(_, ""))
// resultList: scala.collection.immutable.Set[java.io.Serializable] =
// Set(List(5, 4, 3), List(2, 3, 4), List(6, 7), List(1, 2, 3))

Scala: map just first element in tuple

I want to use some function on tuple, which returns tuple with only first element transformed and other elements unchanged.
This is naive version for Tuple2:
def mapFirst[T, U, R](tuple: (T, U))(f: T => R): (R, U) = tuple match {
| case (x, y) => f(x) -> y
| }
mapFirst((1, 2))(_ * 5) // returns (5, 2)
Though, it doesn't feel native, what I want is to write it this way:
(1, 2).mapFirst(_ * 5)
I wrote implicit conversion then:
class RichTuple[T, U](tuple: (T, U)) {
def mapFirst[R](f: T => R): (R, U) = tuple match {
case (x, y) => f(x) -> y
}
}
implicit def tuple2RichTuple[T, U](tuple: (T, U)): RichTuple[T, U] = new RichTuple(tuple)
(1, 2).mapFirst(_ * 5)
Then, when I'll want to map just second element or first element on Tuple3, I'll have to write same boilerplate again. Is there some library which has such methods built-in?
You can use shapeless tuple functions:
import shapeless._
import syntax.std.tuple._
val x=(1,2,3)
val y=x.updatedAt(0,x.head*5)
// y= (5,2,3)
We are able to use _1 as tuple's field. One more solution, just using standard library:
val x = (1, 2, 3)
val y = x.copy(_1 = x._1 * 5)
You could use case classes rather than tuples (this is good style) then use the named elements, e.g.
case class Pie(filling: String, weight: Double, servings: Int)
val p = Pie("cheese", 500.0, 2)
val q = p.copy(filling = "potato")
val r = p.copy(weight = 750.0, servings = 3)

Conditionally apply a function in Scala - How to write this function?

I need to conditionally apply a function f1 to the elements in a collection depending on the result of a function f2 that takes each element as an argument and returns a boolean. If f2(e) is true, f1(e) will be applied otherwise 'e' will be returned "as is".
My intent is to write a general-purpose function able to work on any kind of collection.
c: C[E] // My collection
f1 = ( E => E ) // transformation function
f2 = ( E => Boolean ) // conditional function
I cannot come to a solution. Here's my idea, but I'm afraid I'm in high-waters
/* Notice this code doesn't compile ~ partially pseudo-code */
conditionallyApply[E,C[_](c: C[E], f2: E => Boolean, f1: E => E): C[E] = {
#scala.annotation.tailrec
def loop(a: C[E], c: C[E]): C[E] = {
c match {
case Nil => a // Here head / tail just express the idea, but I want to use a generic collection
case head :: tail => go(a ++ (if f2(head) f1(head) else head ), tail)
}
}
loop(??, c) // how to get an empty collection of the same type as the one from the input?
}
Could any of you enlighten me?
This looks like a simple map of a Functor. Using scalaz:
def condMap[F[_],A](fa: F[A])(f: A => A, p: A => Boolean)(implicit F:Functor[F]) =
F.map(fa)(x => if (p(x)) f(x) else x)
Not sure why you would need scalaz for something so pedestrian.
// example collection and functions
val xs = 1 :: 2 :: 3 :: 4 :: Nil
def f1(v: Int) = v + 1
def f2(v: Int) = v % 2 == 0
// just conditionally transform inside a map
val transformed = xs.map(x => if (f2(x)) f1(x) else x)
Without using scalaz, you can use the CanBuildFrom pattern. This is exactly what is used in the standard collections library. Of course, in your specific case, this is probably over-engineered as a simple call to map is enough.
import scala.collection.generic._
def cmap[A, C[A] <: Traversable[A]](col: C[A])(f: A ⇒ A, p: A ⇒ Boolean)(implicit bf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
val b = bf(col)
b.sizeHint(col)
for (x <- col) if(p(x)) b += f(x) else b += x
b.result
}
And now the usage:
scala> def f(i: Int) = 0
f: (i: Int)Int
scala> def p(i: Int) = i % 2 == 0
p: (i: Int)Boolean
scala> cmap(Seq(1, 2, 3, 4))(f, p)
res0: Seq[Int] = List(1, 0, 3, 0)
scala> cmap(List(1, 2, 3, 4))(f, p)
res1: List[Int] = List(1, 0, 3, 0)
scala> cmap(Set(1, 2, 3, 4))(f, p)
res2: scala.collection.immutable.Set[Int] = Set(1, 0, 3)
Observe how the return type is always the same as the one provided.
The function could be nicely encapsulated in an implicit class, using the "pimp my library" pattern.
For something like this you can use an implicit class. They were added just for this reason, to enhance libraries you can't change.
It would work like this:
object ImplicitStuff {
implicit class SeqEnhancer[A](s:Seq[A]) {
def transformIf( cond : A => Boolean)( f : A => A ):Seq[A] =
s.map{ x => if(cond(x)) f(x) else x }
}
def main(a:Array[String]) = {
val s = Seq(1,2,3,4,5,6,7)
println(s.transformIf(_ % 2 ==0){ _ * 2})
// result is (1, 4, 3, 8, 5, 12, 7)
}
}
Basically if you call a method that does not exists in the object you're calling it in (in this case, Seq), it will check if there's an implicit class that implements it, but it looks like a built in method.

How to modify a value of a Map which contains Sets, returning a new Map?

Given a Map[Int, Set[Int]], how can I modify a single value of the Map, generating a new one in the process, for example:
val x = Map(1 -> Set(1,2,3))
x(1) + 5 // This creates a new Set, but not a new Map
val y = x(1) change { x => x + 5 }
// The previous functionality is what I'm looking for
// z: Set[Int]] = List(Set(1, 2, 3, 5))
As Robin Green suggests, lenses are made for this job. In fact, you want a partial lens, since a map is a partial function of key -> value.
Scalaz 7 includes the mapVPLens function to make a partial lens (PLens) to the value at a chosen key:
import scalaz.PLens._
val x = Map(1 -> Set(1,2,3))
mapVPLens(1) mod ((_: Set[Int]) + 5, x) // Map(1 -> Set(1, 2, 3, 5))
Modifying the value at a non-existent key will have no effect:
mapVPLens(9) mod ((_: Set[Int]) + 5, x) // Map(1 -> Set(1,2,3))
In scala 2.10:
implicit class ChangeableMap[K,V]( val m: Map[K,V] ) extends AnyVal {
def change( k: K )( transform: V => V ): Map[K,V] = {
m.get( k ).map{ v => m + (k-> transform(v)) }.getOrElse( m )
}
}
Some test:
scala>val x = Map(1 -> Set(1,2,3), 2 -> Set(4,5))
x: scala.collection.immutable.Map[Int,scala.collection.immutable.Set[Int]] = Map(1 -> Set(1, 2, 3), 2 -> Set(4, 5))
scala> x.change(1) { x => x + 5 }
res1: Map[Int,scala.collection.immutable.Set[Int]] = Map(1 -> Set(1, 2, 3, 5), 2 -> Set(4, 5))
If you're in scala 2.9, this will do:
class ChangeableMap[K,V]( m: Map[K,V] ) {
def change( k: K )( transform: V => V ): Map[K,V] = {
m.get( k ).map{ v => m + (k-> transform(v)) }.getOrElse( m )
}
}
implicit def toChangeableMap[K,V]( m: Map[K,V] ) = new ChangeableMap[K,V]( m )
Use lenses!
However, Scalaz 6, which defines lenses, doesn't have a specific pre-made lens for your situation, which means slightly more work for you - though if your Map is in turn contained in another object, it does have (well-hidden) support for that situation. And Scalaz 7 will have a lens for standalone Maps.
Also, lenses are just pairs of functions, requiring no language support, so you could just roll your own.
Here's one from our codebase.
/**
* Alters a value in a map.
*
* modifyMap :: Map k v -> k -> (Maybe v -> Maybe v) -> Map k v
* See Haskell's Data.Map.alter
*
* #param m the map to modify
* #param key the key to modify the value of
* #param mod a function that takes the existing value (if any) and returns an optional new value
*
* #return the modified map
*/
def modifyMap[K,V](m: Map[K,V], key: K)
(mod: (Option[V] ⇒ Option[V])): Map[K,V] = {
mod(m.get(key)) match {
case Some(newVal) ⇒ m + (key → newVal)
case None ⇒ m - key
}
}
And here's how you use it:
modifyMap(myMap, "someKey") {
case Some(someVal) =>
// present
if (condition)
Some(valueDerivedFrom(someVal)) // provide a new mapping for someKey
else
None // someKey will now be unset
case None =>
// wasn't present
if (condition)
Some(newValue) // provide a new value for someKey
else
None // leave someKey unset
}
A very idiomatic way of solving this problem would be the following (thanks Viktor Klang):
val x = Map(1 -> Set(1,2,3), 2 -> Set(1), 3 -> Set(5))
x.map { case (1, v) => (1, v + 5); case x => x }
// res0: Map(1 -> Set(1, 2, 3, 5))
Or nicely packed into a class as well as an implicit:
class ChangeableMap[K,V](map:Map[K,V]) {
def change(index:K)(f:V => V) = map.map {
case (`index`, v:V) => (index, f(v))
case x => x
}
}
object ChangeableMap {
implicit def fromMap[K,V](map:Map[K,V]) = new ChangeableMap(map)
}
With the previous declaration, the following will work:
x.change(1) { x => x + 5 }
x.change(1) { _ + 5 }
// res1: Map(1 -> Set(1, 2, 3, 5))
Note that this is probably not the fastest solution, given that Scala will (probably, haven't confirmed) iterate over the entire map!
A possibly faster implementation would be the following (though I have not verified if it is actually faster):
class ChangeableMap[K,V](map:Map[K,V]) {
def change(index:K)(f:V => V) = map.get(index) match {
case Some(x) => map + ((index, f(x)))
case None => map
}
}
I think the easiest way would be using scala.collection.mutable.Map.
import scala.collection.mutable.Map
val m = Map(1 -> Set(1,2,3))
m.update(1, m(1) + 5)
// now the Map looks like this: Map(1 -> Set(1,2,3,5))
If you get an immutable Map, you can simply convert it to a mutable one by using:
val n: collection.mutale.Map(m.toSeq: _*)
This also works the other way around, if you need to return an immutable Map.
As mentioned before you can use Partial Lens for this sort of problem, scalaz and Monocle implements it. Here is how you would do it with Monocle:
import monocle.syntax.taversal._ // to use |->>
import monocle.syntax.at._ // to use at
val x = Map(1 -> Set(1,2,3))
x |->> at(1) modify(_ + 5) == Map(1 -> Set(1,2,3,5))

Sequence with Streams in Scala

Suppose there is a sequence a[i] = f(a[i-1], a[i-2], ... a[i-k]). How would you code it using streams in Scala?
It will be possible to generalize it for any k, using an array for a and another k parameter, and having, f.i., the function with a rest... parameter.
def next(a1:Any, ..., ak:Any, f: (Any, ..., Any) => Any):Stream[Any] {
val n = f(a1, ..., ak)
Stream.cons(n, next(a2, ..., n, f))
}
val myStream = next(init1, ..., initk)
in order to have the 1000th do next.drop(1000)
An Update to show how this could be done with varargs. Beware that there is no arity check for the passed function:
object Test extends App {
def next(a:Seq[Long], f: (Long*) => Long): Stream[Long] = {
val v = f(a: _*)
Stream.cons(v, next(a.tail ++ Array(v), f))
}
def init(firsts:Seq[Long], rest:Seq[Long], f: (Long*) => Long):Stream[Long] = {
rest match {
case Nil => next(firsts, f)
case x :: xs => Stream.cons(x,init(firsts, xs, f))
}
}
def sum(a:Long*):Long = {
a.sum
}
val myStream = init(Seq[Long](1,1,1), Seq[Long](1,1,1), sum)
myStream.take(12).foreach(println)
}
Is this OK?
(a[i] = f(a[i-k], a[i-k+1], ... a[i-1]) instead of a[i] = f(a[i-1], a[i-2], ... a[i-k]), since I prefer to this way)
/**
Generating a Stream[T] by the given first k items and a function map k items to the next one.
*/
def getStream[T](f : T => Any,a : T*): Stream[T] = {
def invoke[T](fun: T => Any, es: T*): T = {
if(es.size == 1) fun.asInstanceOf[T=>T].apply(es.head)
else invoke(fun(es.head).asInstanceOf[T => Any],es.tail :_*)
}
Stream.iterate(a){ es => es.tail :+ invoke(f,es: _*)}.map{ _.head }
}
For example, the following code to generate Fibonacci sequence.
scala> val fn = (x: Int, y: Int) => x+y
fn: (Int, Int) => Int = <function2>
scala> val fib = getStream(fn.curried,1,1)
fib: Stream[Int] = Stream(1, ?)
scala> fib.take(10).toList
res0: List[Int] = List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
The following code can generate a sequence {an} where a1 = 1, a2 = 2, a3 = 3, a(n+3) = a(n) + 2a(n+1) + 3a(n+2).
scala> val gn = (x: Int, y: Int, z: Int) => x + 2*y + 3*z
gn: (Int, Int, Int) => Int = <function3>
scala> val seq = getStream(gn.curried,1,2,3)
seq: Stream[Int] = Stream(1, ?)
scala> seq.take(10).toList
res1: List[Int] = List(1, 2, 3, 14, 50, 181, 657, 2383, 8644, 31355)
The short answer, that you are probably looking for, is a pattern to define your Stream once you have fixed a chosen k for the arity of f (i.e. you have a fixed type for f). The following pattern gives you a Stream which n-th element is the term a[n] of your sequence:
def recStreamK [A](f : A ⇒ A ⇒ ... A) (x1:A) ... (xk:A):Stream[A] =
x1 #:: recStreamK (f) (x2)(x3) ... (xk) (f(x1)(x2) ... (xk))
(credit : it is very close to the answer of andy petrella, except that the initial elements are set up correctly, and consequently the rank in the Stream matches that in the sequence)
If you want to generalize over k, this is possible in a type-safe manner (with arity checking) in Scala, using prioritized overlapping implicits. The code (˜80 lines) is available as a gist here. I'm afraid I got a little carried away, and explained it as an detailed & overlong blog post there.
Unfortunately, we cannot generalize over number and be type safe at the same time. So we’ll have to do it all manually:
def seq2[T, U](initials: Tuple2[T, T]) = new {
def apply(fun: Function2[T, T, T]): Stream[T] = {
initials._1 #::
initials._2 #::
(apply(fun) zip apply(fun).tail).map {
case (a, b) => fun(a, b)
}
}
}
And we get def fibonacci = seq2((1, 1))(_ + _).
def seq3[T, U](initials: Tuple3[T, T, T]) = new {
def apply(fun: Function3[T, T, T, T]): Stream[T] = {
initials._1 #::
initials._2 #::
initials._3 #::
(apply(fun) zip apply(fun).tail zip apply(fun).tail.tail).map {
case ((a, b), c) => fun(a, b, c)
}
}
}
def tribonacci = seq3((1, 1, 1))(_ + _ + _)
… and up to 22.
I hope the pattern is getting clear somehow. (We could of course improve and exchange the initials tuple with separate arguments. This saves us a pair of parentheses later when we use it.) If some day in the future, the Scala macro language arrives, this hopefully will be easier to define.