Haskell -- "The last statement in a 'do' construct must be an expression" - haskell

Like it says in the title: What does The last statement in a 'do' construct must be an expression mean? I ended my do block with a putStrLn like it shows in several examples I've seen, and i get an error.
Code:
main = do args <- getArgs
file <-readFile "TWL06.txt"
putStrLn results

Most of the time, it's because your code is mis-aligned and compiler assumes that your "do" block ended prematurely (or has extra code that dont really belong there)

Your last line isn't something like someVar <- putStrLn "hello", by any chance, is it? You'll get that error if you try to do a variable binding on the last line, because it's equivalent to putStrLn "Hello" >>= \someVar -> — it expects there to be an expression at the end.

Incorrect indentation can lead to this error. Also, is good not to use tabs, only spaces.

Related

Why is getArgs evaluated after fmap method argument?

Why does getArgs gets evaluated after the method argument of fmap?
main::IO()
main=do
fpath<-fmap head getArgs
putStrLn fpath
I get the error :
Exception: Prelude.head: empty list
It seems it applies head on something that has not been computed yet.
I first assumed that it might be another rule about lazyness that i am not aware of being new to Haskell so i tried with :
a<-fmap head getLine # no problem
a<-fmap head (readFile [filename]) # again no problem
So why is getArgs special that gets evaluated after ?
If head breaks on empty list, that means that getArgs did already evaluate, because the value [] was produced and matched by head.
Most probably you ran your program from ghci, which can produce such an effect. Since head is unsafe, you should check whether there's at least one argument on the list present.

Haskell: Parse error: module header, import declaration or top-level declaration expected

I am saving some commands in a Haskell script in a .hs file while working thru a Haskell textbook. Here's a small example.
fst (1,2)
snd (1,2)
When I run these commands from the prelude in GHCi, they work fine. When I try to compile the .hs file with these two lines, I get the following:
ch4_test.hs:2:1: error:
Parse error: module header, import declaration
or top-level declaration expected.
|
2 | fst (1,2)
| ^^^^^^^^^
Failed, no modules loaded.
I've googled this error and can't find any explanation what I'm doing wrong.
From a newbie to future newbies: The interactive environment ghci would lead you to believe that you can punch some expressions into an .hs file and run the thing (in a similar fashion to languages like swift and ruby). This is not the case.
Haskell needs an entrypoint called main. Quoting:
Here is a simple program to read and then print a character:
main :: IO ()
main = do c <- getChar
putChar c
The use of the name main is important: main is defined to be the entry point of a Haskell program (similar to the main function in C), and must have an IO type, usually IO ()
Source: https://www.haskell.org/tutorial/io.html
You can't just put any expression in a hs file.
As the error message says, you need a declaration here. For example:
main =
print (fst (1,2)) >>
print (snd (1,2))
I am getting this error but the cause appears to be completely different from anything posted here. And the error message is not at all helpful.
Using Cabal version 3.6.2.0 with GHCI 8.10.7 on MacOS High Sierra (10.13)
I'm working from this page: https://www.tutorialspoint.com/haskell/haskell_modules.htm
specifically the "custom modules" section. There you can see the code I copied and pasted.
Besides the tutorial not mentioning I needed to add "other-modules: Custom" to myfirstapp.cabal, and besides the fact that the sample Custom.hs file includes "if x 'rem' 2 == 0" rather than "if x rem 2 == 0", here is the problem:
Indentation matters!
This line (inside the quotes) does NOT work "if x rem 2 == 0".
This line DOES work " if x rem 2 == 0"!
Indenting by one space is the difference between success and failure.
I'm totally new to Haskell. I've programmed extensively in PHP, Javascript, and Applescript, and dabbled in a dozen others, and this is the first time I've seen white space matter. I assume this is commonly known amongst Haskell veterans, but it would certainly be nice if that was included prominently in the documentation.

attoparsec: succeeding on part of the input instead of failing

I have an attoparsec parser, and tests for it, what annoys me is that if I comment part of the parser and run the tests, the parser doesn't return Left "parse error at line ..." but instead I get Right [].
Note that I'm using parseOnly to make it clear that there'll be no more input.
Otherwise it's nice to get the partially parsed input, it can definitely be useful and I'm glad to have it. However I'd like to be informed that the whole input was not consumed. Maybe to get a character offset of the last consumed letter, or if that's what it takes, at least an option to be returned Left.
If it's relevant, the parser can be found there.
If I comment for instance the line:
<|> PlainText <$> choice (string <$> ["[", "]", "*", "`"])
And run the tests, I get for instance:
1) notes parsing tests parses notes properly
simple test
expected: Right [NormalLine [PlainText "one line* # hello world"]]
but got: Right []
This is from that test.
Depending on if consuming the whole input should be the property of parseNoteDocument or just the tests, I'd extend one or the other with endOfInput or atEnd.
I'd suggest to define a proper Parser for your documents, like
parseNoteDocument' :: Text -> Parsec NoteDocument
parseNoteDocument' = many parseLine
and then define parseNoteDocument in terms of it. Then you can use parseNoteDocument' in the tests by defining a helper that parses a given piece of text using
parseNoteDocument' <* endOfInput
to ensure that the whole input is consumed.

How to call multiple functions within the code in haskell

I would like to call multiple functions from within the code, meaning that by executing the .hs file, all functions named will be executed.
I tried using main with putStrLn, but this is rather complicated and doesn't seem to work.
main = do
putStrLn (myFunction para1 para2)
putStrLn (anotherFunction para1 para2)
This shows the idea, but it obviosly doesn't work. Escpecially because myFunction returns an Integer and not a char.
I hope someone can help. Thank you in advance.
using "print" solved this problem. Thank you.
Escpecially because myFunction returns an Integer and not a char.
You can use print to print things other than strings. print is equivalent to putStrLn . show, so it can print any type that's showable, which Integer is.

Implicit pattern matching the first 2 items of a list

Is there a way to do this in an implicit way:
(originalPath:extractPath:ignoredArgs) <- getArgs
considering I only need the first two args and will ignore the others anyway.
This is just a curiosity/exploring/learning question (just started with Haskell), ignoredArgs does not harm if it's left like this.
I tried
(originalPath:extractPath) <- getArgs
But it fails since extractPath will be of [String] type (instead of String)
Use a wildcard, _
(originalPath:extractPath:_) <- getArgs
to ignore everything after the first two arguments.
You need to have something there to have the two names be bound to Strings, and a wildcard pattern (underscore) is the way to tell the compiler and human readers of the code that you are not interested in further arguments.

Resources