tags:

views:

160

answers:

5

My original code is given below and works fine. I wanted to add range check of 'ind' and in the modified version I added an if statement. When I run it I get a "type error in conditional", and I THINK its because of the output defintion [[String]] not IO()?

Is there anyother way to check for the range of the value held in ind and produce an output like "error"/"outofrange" ?

original code

retrieve :: [Int] -> [[String]] -> [[String]]
retrieve [] dat = [[]]
retrieve ind dat = [exC ind d | d <- dat]

modified code

retrieve :: [Int] -> [[String]] -> [[String]]
retrieve [] dat = [[]]
retrieve ind dat = if ind>3
                       then putStrLn "not found"
                 else [exC ind d | d <- dat]

thanks,

+5  A: 

Replace putStrLn with error. That will cause your program to abort completely (unless something higher level catches the exception.)

The problem with what you've written is that you have declared a pure type, and then are trying to do IO, which isn't allowed.

Ganesh Sittampalam
+2  A: 

You can use a pattern guard for this:

retrieve :: [Int] -> [[String]] -> [[String]]
retrieve [] dat = [[]]
retrieve ind dat | ind <= 3 = [exC ind d | d <- dat]

If you leave it like that you'll get a "Non-exhaustive patterns in function retrieve". You could also add another case with a custom error:

retrieve _ _ = error "Out of range"
Jonas
thanks all! Great help!
pier
+1  A: 

The then branch has type IO (), the else has type [[String]]. The types of the two if branches are different and there is no way to give a type to the whole if that doesn't cause a type conflict with one of the branches.

sth
+6  A: 

There are actually two errors in that code.

  • You need to use error, because it has type String -> a instead of String -> IO ()
  • You apply > to [Int] and Int. Assuming that you want to test whether ind has length at most 3, you will have to call length.

Example:

retrieve :: [Int] -> [[String]] -> [[String]]
retrieve [] dat = [[]]
retrieve ind dat | length ind > 3 = error "not found"
                 | otherwise      = [exC ind d | d <- dat]
Stephan202
The second point doesn't have to be an error. He could have made [Int] an instance of the Ord typeclass. (but I don't think that is the case)
Jonas
forget that... he actually had an literal 3 there..
Jonas
I think you mean making [Int] an instance of the *Num* typeclass, which would actually have worked, but would be a pretty weird thing to do.
Ganesh Sittampalam
+2  A: 

As described in Ganesh's post, you want to do IO in a pure function, which isn't possible.

Ways to express your program (*you'll have to use length ind > 3 anyway)

1 Use error (best way) as shown in the other posts

2 Use pattern guards (non exhaustive patterns-exception will occur)

3 Implement the IO properly:

retrieve ind dat = if ind >= 3
                    then do return [exC ind d | d <- dat ] 
                    else do putStrLn "error"; return [[]]

retrieve will have the type

retrieve :: [Int] -> [[String]] -> IO [[String]]

4 Use Maybe to express that the computation may fail.

retrieve :: [Int] -> [[String]] -> Maybe [[String]]
retrieve [] dat = [[]]
retrieve ind dat | length ind > 3 = Nothing
                 | otherwise      = Just [exC ind d | d <- dat]
Dario