I'm having problems with an exercise, and can not understand the error.
It should be a simple exercise with args:
import System.IO
import System.Environment
main= do
args < - getArgs
nomeficheiro <- return( args !! 0)
putStrnLn ( "Name is" ++ nomeficheiro)
Then i should run it, with : $ ./comando James
The error:
<interactive>:51:1:
parse error on input ‘$’
Perhaps you intended to use TemplateHaskell
I've read other doubts about args at this fórum and I didn't find any answer that could help me
$ ./comando James isn't meant to be run on GHCi. Instead, $ at the start of the line indicates that the following line should be run in your bash/cmd/shell, not in GHCi:
# in your favourite shell, in the correct directory
./comando James
If you want to run main with arguments within GHCi, you can use :main args:
ghci> :main James
Further remarks
Your current code isn't indented correctly, so make sure that you fix this too. Also, you can use let nomeficheiro = head args instead of … <- return …. Keep in mind that this could lead to problems if one doesn't supply any argument to your program, since head [] calls error.
Related
I am trying to :load file "hello.hs" and keep getting the errors below.
I am using WinGHCi 1.0.6.
I have printed just one argument and it worked but when I try to print two arguments I get a Not in scope error as shown below.
My hello.hs code contains the code below.
-----------------hello.hs--------------------
module Main where
import System.Environment
main :: IO ( )
main = do
args <- getArgs --Getting first arg
putStrLn("Hello," ++args!!0)
do args1 <- getArgs putStrLn("Hello," ++args1!!1) --Getting second arg
----------Errors while trying to do :load command --------
hello.hs:6:37: Not in scope: ‘args’
hello.hs:7:13:
The last statement in a 'do' block must be an expression
args1 <- getArgs putStrLn ("Hello," ++ args1 !! 1)
hello.hs:7:50:
Not in scope: ‘args1’
Perhaps you meant ‘args’ (line 5)
Put the putStrLn command on a separate line. The second do is not necessary (in fact, it is necessary not to have it). Additionally, you should know that the compiler views hard tabs as padding out to the next eight-space boundary; so although things look correctly indented here on SO, your code's mixture of tabs and spaces is incorrect. I recommend either using a single tab at the beginning of each line in the do block or converting all tabs to spaces. See also my diatribe on tab styles. So:
main = do
args <- getArgs --Getting first arg
putStrLn("Hello," ++args!!0)
args1 <- getArgs
putStrLn("Hello," ++args1!!1) --Getting second arg
This is the smallest change needed to make things work. Additionally, since I see no reason to believe the arguments will change between the two calls to getArgs, you may as well omit the second call and simply reuse args:
main = do
args <- getArgs
putStrLn("Hello," ++args!!0)
putStrLn("Hello," ++args!!1)
I'm writing rail-compiler (rail is an esoteric language) in Haskell and I get some problems within the main-function of my mainmodule.
1) I want my program to ask wheter I want to run the compiling-pipeline or simply stop after the lexer and write the AST to a file so another compiler can deal with my AST (Abstract Synatx Tree). Here is my program:
module Main (
main -- main function to run the program
)
where
-- imports --
import InterfaceDT as IDT
import qualified Testing as Test
import qualified Preprocessor as PreProc
import qualified Lexer
import qualified SyntacticalAnalysis as SynAna
import qualified SemanticalAnalysis as SemAna
import qualified IntermediateCode as InterCode
import qualified CodeOptimization as CodeOpt
import qualified Backend
-- functions --
main :: IO()
main = do putStr "Enter inputfile (path): "
inputfile <- getLine
input <- readFile inputfile
putStr "Enter outputfile (path): "
outputfile <- getLine
input <- readFile inputfile
putStr "Only create AST (True/False): "
onlyAST <- getLine
when (onlyAST=="True") do putStrLn "Building AST..."
writeFile outputfile ((Lexer.process . PreProc.process) input)
when (onlyAST=="False") do putStrLn ("Compiling "++inputfile++" to "++outputfile)
writeFile outputfile ((Backend.process . CodeOpt.process . InterCode.process . SemAna.process . SynAna.process . Lexer.process . PreProc.process) input)
I get an error in Line 21 (input <- readFile inputfile) caused by the <-. Why?
How should I do it?
2) Next thing is that I want to refactor the program in that way, that I can call it from the terminal with parameters like runhaskell Main(AST) (in that way it should just create the AST) or like runhaskell Main.hs (in that way it should do the whole pipeline).
I hope for your help!
For your error in (1), your program doesn't look syntactically incorrect at line 21 to me. However an error at <- would happen if that line were indented differently from the previous one. I suspect that you are having an indentation error due to mixing tabs and spaces in a way that looks correct in your editor but disagrees with Haskell's interpretation of tabs. The simplest recommendation is to always use spaces and never tabs.
You also have an extra copy of that line later, which you might want to remove.
I also suspect you may need to use hFlush stdin after your putStr's, for them to work as prompts.
For (2), I'd suggest using a library for proper command line argument and option parsing, such as System.Console.GetOpt which is included with GHC, or one of the fancier ones which you can find on Hackage.
I have used the libraries criterion and cmdargs.
When I compile the program completely without cmdargs and run it e.g. ./prog --help then I get some unwanted response from criterion about the possible options and the number of runs etc..
When I compile and run it as below the command line options are first picked up by my code then then read by criterion. Criterion then subsequently reports and error telling me that the option --byte is unknown. I have not seen anything in the criterion documentation how this could be switched off or worked around. Is there a way to clear out the command line options ofter I have read them? Otherwise I would need to use e.g. CPUTime instead of criterion, that is OK to me since I do to really require the loads of extra functionality and data that criterion delivers.
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveDataTypeable #-}
import System.Console.CmdArgs
data Strlen = Strlen {byte :: Int} deriving (Data, Typeable, Show)
strlen = cmdArgsMode $ Strlen {byte = def} &= summary "MessagePack benchmark v0.04"
main = do
n <- cmdArgsRun strlen
let datastring = take (byte n) $ randomRs ('a','z') (mkStdGen 3)
putStrLn "Starting..."
conn <- connect "192.168.35.62" 8081
defaultMain [bench "sendReceive" $ whnfIO (mywl conn datastring)]
Use System.Environment.withArgs. Parse the command line arguments first with cmdArgs, then pass what you haven't used to criterion:
main = do
(flags, remaining) <- parseArgsHowever
act according to flags
withArgs remaining $
defaultMain [ ... ]
Take a look at the criterion source. You should be able to write your own defaultMainWith function that handles args however you want, including ignoring them, or ignoring unknown args, or etc...
I cannot figure out how to make the concise if-then-else notation work, mentioned at [ http://hackage.haskell.org/trac/haskell-prime/wiki/DoAndIfThenElse ]. This works,
import System.Environment
main = do
args <- getArgs
if (args !! 0) == "hello"
then
print "hello"
else
print "goodbye"
but this does not, and inserting said semicolons (see link) just result in parse errors for me.
import System.Environment
main = do
args <- getArgs
if (args !! 0) == "hello" then
print "hello"
else
print "goodbye"
The link you provided describes a proposal, which sounds like it is not part of the Haskell standard (although the link mentions that it's implemented in jhc, GHC and Hugs). It's possible that the version of the Haskell compiler you're using, or the set of flags you're using, does not allow for the optional-semicolon behavior described in the link.
Try this:
import System.Environment
main = do
args <- getArgs
if (args !! 0) == "hello" then
print "hello"
else
print "goodbye"
In Haskell 98 “if … then … else …” is a single expression. If it’s split to multiple lines, the ones following the first one must be indented further.
Just like the following is wrong…
do
1 +
2
…and the following works…
do
1 +
2
…the following is also wrong…
do
if True then 1
else 2
…and the following works.
do
if True then 1
else 2
As the other comments already mention, Haskell 2010 allows the “then” and “else” parts on the same level of indentation as the “if” part.
Haskell syntax and language are extended though {-# LANGUAGE ... #-} pragmas at the start of the source files. The DoAndIfThenElse extension is recognized since it is one of those listed in the Cabal documentation. Current GHC enables this by default.
I usually indent the else one space more than the if. Unless then whole if fits nicely on a single line.
I want to do a popen() / python's subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What's the most direct / Haskellish way to do this?
Pick either MissingH's System.Cmd.Utils and the standard library's System.Process. They're easy to use, with both high-level convenience functions (which you simply throw strings at and get strings back, possibly lazily) and low-level plumbing functions (which actually give you handles, like most popen functions in other languages/frameworks).
import System.Process
main = do
let cmd = "mail"
args = ["root#localhost", "-s", "does this act like popen?"]
input = ["Hello, world!"]
(rc, out, err) <- readProcessWithExitCode cmd args input
putStrLn $ "mail exited: " ++ show rc
mapM_ putStrLn $ map ("out: " ++) $ lines out
mapM_ putStrLn $ map ("err: " ++) $ lines err
The other option could be to use shelly package