1

//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

13
  • "the last line which is the main function of the program works fine without the nested if above": It won't, index' won't even type check... Commented May 17, 2009 at 8:49
  • Regarding your edit: both snippets work fine, I don't get an 'unexpected symbol' error. However, you have given two functions the same name, this way you can't call the second index from the first. Commented May 17, 2009 at 10:52
  • Which of your question have already been answered now? Commented May 17, 2009 at 11:18
  • please refer edit 4. thats the question i need to ask. Commented May 17, 2009 at 11:23
  • What should index do now? Should it check whether who lists are empty and make some output or should it check wheter b is a subset of a? Commented May 17, 2009 at 11:26

4 Answers 4

4

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]
Sign up to request clarification or add additional context in comments.

2 Comments

why dont i need to define the type like index' :: [String] -> [String] -> Bool
The compiler generally can deduce the types automatically, so you don't need to declare them manually if you don't want to. But it's usually better to declare them because it helps to find the problematic code in case of type errors. In this case you could declare the type of index as "[String] -> [String] -> IO ()" or more generally as "(Eq a) => [a] -> [a] -> IO ()".
2

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"

6 Comments

ok, well i tried it this way and i still get an error as "Syntax error in expression (unexpected `}', possibly due to bad layout) " index as bs = if isEmpty as then putStrLn "a is empty" else if isEmpty bs then putStrLn "b is empty" else putStrLn "neither are empty" where index' :: [String] -> [String] -> [Int] index' as bs = index' True [(elem a bs) | a <- as]
You'll need do to sequence the outputs.
Than you probably do have a problem with your layout. Make sure the then and else keywords are indented to at least the level of the if keyword. In your current question, the else is indented wrong. Also, make sure you only use spaces for layout, tabs will mess thing up.
@Dario, the you don't really need do syntax in this example. In this case, the expression will be of type IO (), because putStrLn is of that type. do syntax is just syntax sugar if you want to bind multiple expressions, but that's not necessary here.
I'll have to bind multiple expressions - The programm may output a is empty b is empty
|
0
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.

Comments

0

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!

9 Comments

You won't need the do syntax here, if you remove all the dos, your code will still work.
The empty function here already exists in the Prelude, it's called null and it's defined in exactly the same way.
How would the code look without do? It makes two separate outputs so both conditions and putStrLns must be sequenced monadically = do.
Oh, right, I didn't read your code properly. You are right, you need the outer do. Btw, there is also a function for if b then something else return () called when. You can use it like so: when (empty a) (putStrLn "a is empty"). It is in the Control.Monad module.
You will need do notation to sequence the two calls to when.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.