Babra Cunningham
Babra Cunningham

Reputation: 2967

Iteration using counters in functional programming?

I'm iterating through a list of [Char], I'm wondering the best way to perform the iteration.

This function calls itself recursively and passes back to itself a counter that gets decreased per iteration.

Its just for illustrative purposes, so always return True for each Char:

text = ["abcsdsdsdsd"]

exampleFunction :: Int -> String -> [Bool]
exampleFunction textlen text
  | textlen >= 0        = True : exampleFunction (textlen - 1) text
  | otherwise   = []

Using 'textlen' as a counter seems rather imperative, is this the best way and/or the most Haskell-like to implement this?

Upvotes: 0

Views: 233

Answers (1)

chepner
chepner

Reputation: 531055

The counter isn't necessary. The length of the list isn't particularly important; you just use it to determine if the list is non-empty (textlen >= 0) or not. You can do the same thing by pattern matching on the argument itself.

exampleFunction :: [String] -> [Bool]
exampleFunction (x:xs) = True : exampleFunction xs
exampleFunction []  = []

As pointed out in a comment, this particular recursion scheme is abstracted out as the map function:

exampleFunction :: [String] -> [Bool]
exampleFunction xs = map (const True) xs

where const True returns a function that returns True no matter what its argument is. (const True can also be written as an explicit lambda expression (\_ -> True). map applies this function to each element of xs and combines the results into a new list.

Other recursion schemes capture different styles of recursion (filter, foldr, etc), so while it is always possible to write an explicit recursive function to accomplish your task, you can often avoid it by using the appropriate higher order function.


I'm abusing the term recursion scheme a bit; map and filter can be thought of as special cases of foldr, which is an example of a general recursion scheme known as a catamorphism.

Upvotes: 2

Related Questions