1

i am learning Haskell from learnyouhaskell.com and got this error message when compiling my program.

Error:

baby.hs:25:26: error:
    parse error on input `='
    Perhaps you need a 'let' in a 'do' block?
    e.g. 'let x = 5' instead of 'x = 5'

Code:

bump :: [String] -> IO ()
bump [fileName, numberString] = do
    handle <- openFile fileName ReadMode
    (tempName, tempHandle) <- openTempFile "." "temp"
    contents <- hGetContents handle
    let number = read numberString
        text = lines contents
        bumpLine = text !! number
        newText = delete (text !! number) text
    hPutStr tempHandle $ unlines (bumpLine:newText)
    hClose handle
    hClose tempHandle
    removeFile fileName
    renameFile tempName fileName

Can anyone help me with this?

Tobias Marschall
  • 2,355
  • 3
  • 22
  • 40
  • 1
    This might be a tabs problem. Try to remove the tab characters for indentation and use spaces instead. – Bakuriu Sep 29 '16 at 08:13
  • 1
    @Bakuriu I verified it is a tab problem - in the lines after the let expression the indentation has to be with spaces (and in addition it is mixed tabs/spaces) - I guess your comment would be the answer (and I wouldn't have spotted that ever) – epsilonhalbe Sep 29 '16 at 08:22
  • 1
    Thank you. Now it´s working. Is there any workaround for using haskell with tab characters? – Tobias Marschall Sep 29 '16 at 08:31
  • 2
    @TobiasMarschall You can but you have to be *extremely* careful. There even was [a proposal to exclude tab as a valid indentation character](https://prime.haskell.org/wiki/Tabs). In particular if you want to be sure to look at the code in the same way that the compiler sees it you have to use a tabstop of **8** characters (i.e. visually each tab should be 8 spaces wide). AFAIK on modern editors the default is 4 or 2. Also you should **never** mix tab and spaces. A lot of editors have an option to make starting and trailing spaces/tabs visible: you should definitely use that. – Bakuriu Sep 29 '16 at 09:02
  • 3
    Also: [newer versions of ghc by default warn when they see a tab used for indentation](https://ghc.haskell.org/trac/ghc/ticket/9230). BTW: I hope that you are aware that editors can be configured to insert `n` spaces instead of a tab character and some editors can be configured so that when moving the cursor in the indentation the cursor moves by "levels" so that you don't end up having to move it for 4x (or 2x or 8x) the number of characters etc. In other words: if you have a proper editor *everything* you do with tabs can be achieved with spaces too. – Bakuriu Sep 29 '16 at 09:07

1 Answers1

4

As you verified the issue is that you are using tabs for indentation which is generally a bad idea, especially in languages where indentation is significant and especially when you mix tabs and spaces.

The compiler/interpreter has to convert those tab to a certain number of spaces to understand the indentation level of the code, and the conversion that it does can be different from what you are visually seeing and as such you can end up with code that looks fine to you, but not to the compiler/interpreter.

In this case it seems like the parser of ghc is not seeing the following declarations of your let inside the let, but as if they were like this:

let number = read numberString
text = lines contents

And it is telling you that the text = lines contents line is missing a let.

Just use spaces for Haskell and you'll never have this issue again.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • 3
    most (modern) editors have a "replace tabs with spaces" option - if you're using vim it is for example `set expandtab` in your `.vimrc`-file – epsilonhalbe Sep 29 '16 at 08:57