I originally wrote it more or less like this:

def pairMap[A,B](previous:A, aList:List[A], f: (A, A) => B): List[B] = aList match {

case Nil => Nil

case head :: tail => f(previous, head)::pairMap(head, tail, f)

}

I was using it in the context of getting a list of gaps between the numbers of a list:

def getGapList(aList: List[int]) = pairMap(aList.head, aList.tail, (a:Int, b:Int)=>(b - a))

Usage example:

val list = List(2, 5, 9)

list: List[Int] = List(2, 5, 9)

getGapList(list)

res1: List[Int] = List(3, 4)

The other day, reminiscing about the Fibonacci example in "A Gentle Introduction to Haskell Version 98", a different implementation occurred to me. Unsurprisingly, it involves zipping a list with itself 8)

Thinking about folds, I thought I might as well put an initial value.

def pairMapWithInitial[A,B](initial:A, aList:List[A], f: (Tuple2[A, A]) => B):List[B] = {

initial::aList zip aList map f

}

def getGapListWithInitial(initial:int, aList:List[int]) = pairMapWithInitial(initial, aList, (a:Tuple2[Int,Int])=>(a._2 - a._1))

Usage example:

getGapListWithInitial(list.head, list.tail)

res2: List[Int] = List(3, 4)

getGapListWithInitial(0, list)

res3: List[Int] = List(2, 3, 4)

Because it's clearer to me, I still prefer the first version with "match", but it was a nice exercise to explore the zip version.

Post update

A similar version can be written using the List.map2 function which is pretty similar to a zip and map except the function takes two arguments instead of a tuple.

def pairMapWithInitial[A,B](initial:A, aList:List[A], f: (A, A) => B): List[B] = {

List.map2(initial::aList, aList) (f)

}

def getGapListWithInitial(initial:int, aList:List[int]) = pairMapWithInitial(initial, aList, (a:Int, b:Int)=>(b - a))