[Haskell-beginners] Parse error in pattern

Florian Duret flo.morphe at gmail.com
Sat Feb 27 07:17:38 EST 2010


Thank you Daniel, this helps a lot !

As you can guess, I come from the imperative world, but want to discover
functionnal languages (thanks to xmonad).

Thank you very much for your explainations. I think I will fall in that trap
again, but next time, I should be able to fix it myself. I still don't
understand exactly what lies behind, but start to get the picture. I didn't
change anything besides the position of the 'do' and the deletion of the
'return ()'.
I will modify the code with the realWork function as you suggested. I looks
much nicer.

As of the last problem, with the intToDigit function. I already knew about
the bug. I actually knew it wouldn't work since it is takes only argument
from 0 to 15... Well, that was lazy from me. I just wanted to write the
statement so that I don't forget it.

Danke sehr.



2010/2/26 Daniel Fischer <daniel.is.fischer at web.de>

> Am Freitag 26 Februar 2010 18:34:35 schrieb Florian Duret:
> > It seems that both your suggestions have worked ! Thank you very much.
> > But I still can't figure out what went wrong.
>
> Did you change anything besides removing the "do" and "return ()" from the
> then-branch and insert the "do" in the else-branch?
> If not, you've been bitten by a somewhat less than obvious aspect of layout
> - although it's pretty clear with an explanation.
> A new layout-block isn't opened by a larger indentation, but by the
> keywords do, let, of and where.
> So, when you write
>
> ... = do
>  xxx
>  if blah
>    then do
>      foo
>      bar
>    else
>      baz
>      zap
>
> the "do" after the then opens a new layout-block inside the big do-block,
> since you didn't insert an explicit  brace. The indentation level thereof
> is determined by the 'f' of "foo", bar is indented to the same level as
> foo, so it's a new expression in that same block.
> The else is indented less than the foo, so that ends the inner layout-block
> and we return to the layout-block of the big do-block. The indentation
> level thereof is determined by the first 'x', and the "if" is indented to
> the same level.
> The else, the baz and the zap are all indented further than the if, so they
> all belong to the if-expression (as intended).
> But since there's no "do" after the "else", all that is on one logical
> line, it's parsed as
>
> ... = do
>  xxx
>  if blah then do { foo; bar } else baz zap
>
> Not what was intended, but it parses just fine.
>
> Now you didn't have
>
>      baz
>      zap
>
> but
>
>      baz <- bong
>      zap
>
> and since we're still having only one logical line for the if-expression,
> the parser sees that as
>
> ... = do
>  xxx
>  if blah then do { foo; bar } else baz <- bong zap
>
> But the syntax is
>
>  pattern <- expression
>
> so the parser tries to parse
>
>  if blah then do { foo; bar } else baz
>
> as a pattern. But it doesn't conform to the pattern productions, hence the
> parse error.
>
> >
> > My initial goal was to keep the minimum inside the if ... then ... else
> > statement. Basically, if the list is empty, then stop. If not, then
> > assign the argument to sacFile1, and go on with the rest.
>
> It would be cleanest to have
>
> realWork :: FileName -> IO ()
> realWork file = do
>    sacFile1 <- openBinaryFile file ReadMode
>    ...
>
> main :: IO ()
> main = do
>    argList <- getArgs
>    case argList of
>      []    -> putStrLn "No filename ..."
>      (f:_) -> realWork f
>
> or
>
>    if null argList
>      then putStrLn "..."
>      else realWork (head argList)
>
> , je pense.
>
> >
> > Here is what it looks like now:
> > module Main () where
> >
> > import System.IO
> > import System.Environment(getArgs)
> > import Data.Char(intToDigit)
> >
> > import SAC_Type
> > import SAC_IO
> >
> > main :: IO()
> > main = do
> >      -- On commence par ouvrir le fichier SAC en mode binaire
> >      argsList <- getArgs
> >      if (null argsList)
> >         then
> >               putStrLn $ "No filename given to the program.\n $
> > ProgramName file.sac"
> >         else do
> >            sacFile1 <- openBinaryFile (head argsList) ReadMode
> >
> >            position <- hTell sacFile1
> >            putStrLn $ "Position 1: " ++ [intToDigit( fromInteger
> > (position) )]
> >
> >            hSeek sacFile1 AbsoluteSeek 440
> >            position2 <- hTell sacFile1
> >            putStrLn $ "Position 2: " ++ [intToDigit( fromInteger
> > (position2) )]
>
> I don't think that's what you really want:
>
> Prelude Data.Char> intToDigit 440
> *** Exception: Char.intToDigit: not a digit 440
>
> perhaps you wanted
>
>        putStrLn $ "Position 2: " ++ show position2
>
> ?
>
> >
> >            -- A la fin, il faut evidemment le fermer
> >            hClose sacFile1
> >
> >
> > Thank you, Danke, 谢谢, merci, etc...
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20100227/1e28fbd6/attachment-0001.html


More information about the Beginners mailing list