How to chain function calls by a list

I have question about “functional chaining”. Say, I have a list

myList:  List[MyInput]

a) When I have a function

def myMapFunc (x:MyInput): MyData = ...

I can easily map over the list:

result: List[MyData] = myList.map(myMapFunc)

b) Now I have a function

def myChainfunc (x: MyInput, old: MyData): MyData

and I want to chain all the MyInput elements in myList via myChainfunc. So for a 3-element myList I could write it out like this:

result: myData = myChainFunc(myList(2), myChainFunc(myList(1), myChainFunc(myList(0), startMyData)))...

How can I write this chain application for a general n-element list? And how can I do so functionally, i.e. without a for loop, but with some map-like operator?

In Haskell, I think, I would have used some sort of fold; what do I use in Scala 3?

Simple foldLeft would probably would be the most idiomatic:

trait Input
trait Data

def func(x:Input, old: Data): Data = ???

val inputs: Seq[Input] = ???
val initialState: Data = ???
inputs.foldLeft(initialState){case (state, input) => func(input, state)}
// or simply 
inputs.foldRight(initialState)(func(_, _)) 
// which is the same as 
inputs.foldRight(initialState){case (input, state) => func(input, state)}
3 Likes

foldRight expects a function with that signature, so you can even write inputs.foldRight(initialState)(func), without wrapping it in a lambda. Also, the case is usually not needed, unless the function is expected to accept a tuple.

As you mention Haskell, a tip if you know a function in Haskell, but can’t find the Scala equivalent: the Scala 3 documentation can search by signature, so you can find foldLeft with List[A] => B => ((B,A) => B) => B (sadly, it requires the correct order of parameters, which sometimes differ from Haskell, so you may have to try several).
If you want to write purely functional code, you may also want to look into the libraries Cats or ZIO Prelude, which both add various functional abstractions and functions (the former being closer to Haskell).

2 Likes

@WojciechMazur Thanks for the details!

foldRight worked out of the box the way func was given.

However I need application the other way round and I can change the signature of func, so that’s what I did and now it works directly with `foldLeft. :slight_smile:

How cool is that! Looks to me like a “Hoogle for Scala”.

Thanks for point it out to me. It will help me.