What role does the indentation play here? and Why one indent doesn't work?
Here is a sample program from RWH book. I'm wondering why the first works great but the second can't even compile? The only difference is the first one uses 2 tabs after where mainWith func = do
whereas the second uses only 1. Not sure what difference does that mean? Why the second fails to compile? And also why do construct
can be empty?
Thanks a lot, A开发者_开发知识库lex
-- Real World Haskell Sample Code Chapter 4:
-- http://book.realworldhaskell.org/read/functional-programming.html
import System.Environment (getArgs)
interactWith func input output = do
s <- readFile input
writeFile output (func s)
main = mainWith myFunction
where mainWith func = do
args <- getArgs
case args of
[fin, fout] -> do
interactWith func fin fout
_ -> putStrLn "error: exactly two arguments needed"
myFunction = id
-- The following code has a compilation error
-- % ghc --make interactWith.hs
-- [1 of 1] Compiling Main ( interactWith.hs, interactWith.o )
--
-- interactWith.hs:8:26: Empty 'do' construct
import System.Environment (getArgs)
interactWith func input output = do
s <- readFile input
writeFile output (func s)
main = mainWith myFunction
where mainWith func = do
args <- getArgs
case args of
[fin, fout] -> do
interactWith func fin fout
_ -> putStrLn "error: exactly two arguments needed"
myFunction = id
The definition of the mainWith
function is indented to column 10:
where mainWith func = do
^
The contents of the do
block started in this line are only indented to column 8:
args <- getArgs
case args of
...
^
If you increase the indentation of the contents of the do
block to be also indented at least to column 10, the code is parsed correctly. With the current indentation the lines that should belong to the do
block are seen to be part of the where
clause, but not the mainWith
function.
The do
-block can not be empty, that's why you get the error. When using only one tab args <- getArgs
is seen as part of the where
-block, not the do
-block, so the do
-block is empty and you get an error.
The thing is that unless you use {}
and ;
to explicitly state which block goes from where to where, haskell relies on indendation. And since you indented your line only by one level, it was seen as part of the where
-block.
精彩评论