pier
pier

Reputation: 503

nested if in haskell

//edit 5 when the i use only these 2 lines

  index :: [String] -> [String] -> Bool
  index a b = and [x `elem` a |x <- b]

it works fine!!!!

eg:

index ["asd","asdd","dew"] ["asdd","asdad"]

False

But when i use the entire code mentioned below

empty [] = True
empty _ = False

    index a b = do
             if empty a
              then do putStrLn "a is empty"
                      else return ()
             if empty b
              then do putStrLn "b is empty"
                      else return ()
        where
          index :: [String] -> [String] -> Bool
          index a b = and [x `elem` a |x <- b]

theres no output!! and thats the issue i got!!

//edit 6

index a b = do index'
         if empty a
          then do putStrLn "a is empty"
                  else return ()
         if empty b
          then do putStrLn "b is empty"
                  else return ()
    where
      index' :: [String] -> [String] -> Bool
      index' a b = and [x `elem` a |x <- b]

thanks

Upvotes: 1

Views: 6077

Answers (4)

Nathan Shively-Sanders
Nathan Shively-Sanders

Reputation: 18389

This is a little off-topic since maybe you are trying to learn the layout rule and how to nest ifs, but the code you show in revision 6 is just using if to do error checking. I would just do the error checking via pattern matching instead of if.

index [] _ = putStrLn "a is empty"
index _ [] = putStrLn "b is empty"
index a b = putStrLn (show index')
    where index' = and [x `elem` a | x <- b]

(You don't need the return () after putStrLn because it already returns () for you.)

Pattern matching is a lot easier to get right because it doesn't require a lot of indentation, etc.


Edit:

I changed the definition of index' a little from yours. In my version it's a local variable instead of a local function. In Haskell, there's not much difference, it's just that index' uses a and b from the surrounding index function, so it doesn't need to take parameters. (Admittedly, index' is not such a good name for a variable.)

Also I left off the type annotation because I don't usually write them. But they are helpful when something isn't working. Here is what it would look like:

    where index' :: Bool
          index' = and [x `elem` a | x <- b]

Upvotes: 4

Dario
Dario

Reputation: 49208

IO operations in Haskell are a bit difficult because they need so called monads You would need a special do-notion here to sequence the outputs.

Write it like this:

empty [] = True
empty _ = False

index a b = do
         if empty a
          then do putStrLn "a is empty"
          else return ()
         if empty b
          then do putStrLn "b is empty"
          else return ()

Or Maybe you could just return the strings and use putStrLn separately. You index' must return a boolean value when it should be used as an if condition!

Upvotes: 0

Tom Lokhorst
Tom Lokhorst

Reputation: 13768

An if construct in Haskell is a expression. That means it must always evaluate to a value, so the else part is mandatory.

Also, the first part of if must be a boolean, so you can't call index' there, since that returns a [Int], not a Bool.

I would say, start with something like this:

if isEmpty a
then putStrLn "a is empty"
else if isEmpty b
     then putStrLn "b is empty"
     else putStrLn "neither are empty"

Upvotes: 2

apostlion
apostlion

Reputation: 720

index a b = if index' [] bs
                       then putStrLn "a is empty"
                       if index' a []          
                        then putStrLn "b is empty"
                        else                  
    where 
        index' :: [String] -> [String] -> [Int]
        index' a b = index' True [(elem x b) | x <- a]

If you indent your statement like this you'll see that the first if has no matching else clause.

Also, else clause doesn't return anything — a function should have a return value under all circumstances.

Upvotes: 0

Related Questions