CSJC
CSJC

Reputation: 35

parse error on input 'else' on an If-Then-Let-Else statement (Haskell)

This portion of code checks if a number given (First element in a list) is zero (yes i tried == 0 but got other errors) It then return all elements of another list except the first one. If not, it returns another list. The function is of type [a] and 'newpack' needs to be a variable as it is used later.

                              if ((position!!1) < 1)
                                then 
                                    let newpack =   drop ((length pack)-1) pack
                                else
                                    let newpack = (take ((position!!1)-1) pack) ++ (drop ((position!!1)+1) pack)

error is 46:73: parse error on input `else'

Do have any idea why this is not working? Is it that'let's needs an 'in' with them?

Thanks for your help,

J

Upvotes: 0

Views: 3643

Answers (2)

ehird
ehird

Reputation: 40807

Yes, the in part is not optional. You can write this as:

let newpack = if (position !! 1) < 1
                then drop ((length pack)-1) pack
                else (take ((position!!1)-1) pack) ++ (drop ((position!!1)+1) pack)
in ...rest of code...

If you're in a do block, then you can omit in onwards, but either way, you can't put the conditional outside the binding.

(If you're hoping to modify newpack as if it was a mutable variable, that's just not possible; all let does is give a name to a value, you can't actually modify anything. But how to structure your code without this would be beyond the scope of this question; if you need help with that, you should ask another.)

Some stylistic notes:

  • Explicit list indexing is generally considered a bad idea; depending on what it's used for, you might want to consider making position a tuple or some other data structure.

  • Similarly, length is probably a bad idea too (it has to traverse the entire list just to give a result).

  • You have a lot of redundant parentheses: drop ((length pack)-1) can be simply drop (length pack - 1).

A nicer way to write this (from a purely aesthetic point of view — i.e. ignoring the list indexing and use of length) would be (using guards):

let firstPos = position !! 1
    newPack
      | firstPos == 0 = drop (length pack - 1) pack
      | otherwise     = take (firstPos - 1) pack ++ drop (firstPos + 1) pack
in ...

Upvotes: 4

Daniel Wagner
Daniel Wagner

Reputation: 153352

Is it that 'let's needs an 'in' with them?

Yes. (do-blocks are a special case; however, even in a do-block, the rest of the block is a bit like being in an implicit in.) You might consider writing something like this:

let newpack = if {- ... -} then {- ... -} else {- ... -} in
{- the rest of your computation that uses newpack -}

Upvotes: 2

Related Questions