Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we limit recursive calls in Haskell?

I've got a problem with my code, which is the following:

import Data.List

splitat _ [] = ([],[])
splitat element (head:tail)
  | element == head = ([],(head:tail))
  | otherwise = ([head]++fst(splitat element tail), snd(splitat element tail))

It splits a list at 'element', then combining the left and right sublist into a tuple. However, in the third line, the 'splitat element tail' command is called twice, once through 'fst' and once through 'snd'. Is there a way to evaluate this term only 1 time to keep the recursion tree narrow?

Thanks in advance.

like image 863
TimzyPatzy Avatar asked Dec 16 '19 14:12

TimzyPatzy


People also ask

How do you stop recursive calls?

A recursive function is a function that makes a call to itself. To prevent infinite recursion, you need at least one branch (i.e. of an if/else statement) that does not make a recursive call. Branches without recursive calls are called base cases; branches with recursive calls are called recursive cases.

How does Haskell handle recursion?

Basically by the time Haskell gets to evaluating the recursive call to getCommandsFromUser , it's already done with all of the data generated within the previous iteration, and so it gets garbage collected. So you can keep running this program indefinitely without needing more than a fixed amount of memory.

How do you limit the depth of recursion?

The recursion depth limit in Python is by default 1000 . You can change it using sys. setrecursionlimit() function.

Is there a limit to recursion?

Python's default recursion limit is 1000, meaning that Python won't let a function call on itself more than 1000 times, which for most people is probably enough. The limit exists because allowing recursion to occur more than 1000 times doesn't exactly make for lightweight code.


1 Answers

Yes. You can make use of a let expression, or a where clause. For example:

splitat :: Eq a => a -> [a] -> ([a], [a])
splitat _ [] = ([],[])
splitat x' xa@(x:xs) | x == x' = ([], xa)
                     | otherwise = (x:ys1, ys2)
    where (ys1, ys2) = splitat x' xs

Note: please do not use head :: [a] -> a or tail :: [a] -> [a] or other functions that are defined as variables, since these will shadow the existing binding. It makes it harder to reason about the code, since a person might think that head and tail refer to these functions, and not the variables.

like image 77
Willem Van Onsem Avatar answered Sep 28 '22 00:09

Willem Van Onsem