0

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?

Erik
  • 88,732
  • 13
  • 198
  • 189
Kerry
  • 1
  • 1
  • 1
  • 1
    What about checking if there is a negative value in `(a:as)` before calling `func2 x a:func x as`? – Oscar Mederos May 02 '11 at 06:42
  • Do you mean to stop the whole process of func whenever any element of any of the lists is negative? If so, what do you want func to return? The input list? – Ptival May 02 '11 at 06:46

3 Answers3

5

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 
hammar
  • 138,522
  • 17
  • 304
  • 385
  • that's what I understood first, but I think he might want to stop func2 from being applied at all whenever one list contains a negative value... – Ptival May 02 '11 at 06:49
  • Well the problem i have stems from the concept of unification. Where we look for rules to add and when we come across a rule like X -> f(x) we return a fail because the right hand side contains an x. now im not sure if you have seen unification before. so ill just be more specific on the problem at hand. – Kerry May 02 '11 at 08:06
1

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.

Landei
  • 54,104
  • 13
  • 100
  • 195
  • func deals with lists of lists of Ints, not lists of ints. – Ptival May 02 '11 at 06:48
  • yes, but i dont see the reason for downvote. he wrote a terminating base-case for negative inputs using a guard. after reading the question, thats what i consider to be the important characteristic of an answer. OP can adjust from there. – jon_darkstar May 02 '11 at 07:04
  • @jon_darkstar: see hammar's edited answer, I think that's more of what Kerry expected. But I must admit that the question is a bit unclear. – Ptival May 02 '11 at 07:41
  • @Ptival: To downvote just because I was guessing is not very nice. But you know how karma works, I'll have an eye on the quality of **your** answers :-P – Landei May 02 '11 at 08:01
  • @Landei: Fair enough. (But for the record I decided to downvote because of the other problem, i.e. the mismatch of you answer to the question in terms of signature). Whatever... Be sure to haunt my every post, you'll have plenty of opportunities to avenge this! ^^ (and make the world better) – Ptival May 02 '11 at 09:26
  • Okay the problem I have is parsing a variable around functions. So a variable that is constantly being updated, accessed, read from etc. I dont know how to deal with that in haskell? – Kerry May 02 '11 at 11:37
0

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