How to Write a Simple Recursive Double Loop in Haskell Without Map or List Comprehensions

Viewed 94

I'm trying to understand recursion so I thought I'd write a simple double for-loop with just raw Haskell (no list comprehensions, no map, etc.).

Given i and j produce the following ..

rTest01 2 5

[[2,5],[2,4],[2,3],[2,2],[2,1],[1,5],[1,4],[1,3],[1,2],[1,1]]

My code works but it doesn't seem beautiful .. I had to add an additional argument to reload the 'j' every time 'i' changes.

Is there a cleaner way to write it?

rTest01 :: Int -> Int -> [[Int]]
rTest01 i j =
      [[i,j]] ++ rTest01' j i (j-1)

rTest01' :: Int -> Int -> Int -> [[Int]]
rTest01' origJ i 0 = rTest01' origJ (i-1) origJ
rTest01' _ 0 _ = []
rTest01' origJ i j  =
    [[i,j]] ++ rTest01' origJ i (j-1)
1 Answers

This is a good use case for internal recursion. In the same way that, in Python or Java, we might have a private recursive function that's only called by a public non-recursive function (where the latter doesn't take the extra "helper" arguments), we can do the same thing in Haskell using nested scopes.

example :: Int -> Int -> [(Int, Int)]
example iorig jorig = go iorig jorig
    where go 0 _ = []
          go i 0 = go (i - 1) jorig
          go i j = (i, j) : go i (j - 1)

While I definitely appreciate your practice with recursion, and I do emphasize that it is a very good exercise to write code like this, as it practices many basic skills necessary for more complex Haskell coding, do remember that, even when written the way I have above, this is not idiomatic Haskell. If I was writing this function in production, I'd write

example :: Int -> Int -> [(Int, Int)]
example i j = reverse $ (,) <$> [1..i] <*> [1..j]

(Removing the reverse if we don't care about the order)

Recursion is a very handy skill to have, but it's not always the solution. And indeed, in Haskell, there are often several other abstractions we can build upon to make our code simpler, such as applicatives and monads in the above example.

Good luck and happy coding! :)

Related