Kerry
Kerry

Reputation: 1

How to terminate in a recursive function in Haskell?

I have a function that needs to terminate on a certain condition. So for example say we have the following functions:

func :: Int -> [[Int]] -> [[Int]]

func _ [] = []

func x (a:as) = func2 x a:func x as

func2 :: Int -> [Int] -> [Int]

func2 _ [] = []

func2 x (a:as) = x*a:func2 x as

Lets say that I want func one to be called as normal but whenever we get a negative value in the [[Int]] input, we terminate. so we only deal with positive values. so How could you make func2 send some signal to quit the whole process rather than continuing?

Upvotes: 0

Views: 7622

Answers (3)

solrize
solrize

Reputation: 1

If you don't mind traversing the lists in func2 twice, this might work:

import Data.Maybe

func :: Int -> [[Int]] -> [[Int]]
func a xss = map fromJust . takeWhile isJust . map (func2 a) $ xss

func2 :: Int -> [Int] -> Maybe [Int]
func2 a xs
  | any (< 0) xs = Nothing
  | otherwise = Just . map (*a) $ xs

Upvotes: 0

hammar
hammar

Reputation: 139890

First of all, your functions can be written more simply as

func1 x = map (func2 x)
func2 x = map (*x)

Now it is easy to change func2 to stop when a negative value is encountered:

func2 x = map (*x) . takeWhile (> 0)

EDIT:

So if I understand this right, you want the entire computation to fail if a negative value is encountered. One way to do this is to wrap the result in a Maybe. We can then write this in a monadic style:

func1 :: Int -> [[Int]] -> Maybe [[Int]]
func1 x = mapM (func2 x)

func2 :: Int -> [Int] -> Maybe [Int]
func2 x as = do
    guard $ all (>= 0) as
    return $ map (*x) as 

Upvotes: 5

Landei
Landei

Reputation: 54584

I'm not really sure what you mean, but I'll give it a shot:

func _ [] = []
func x (a:as) | a < 0 = []
              | otherwise = func2 x a:func x as

This terminates the calculation for a negative value in the same way an empty list would do. I hope this is what you want.

Upvotes: 0

Related Questions