Haskell use main load a file , how to write address - haskell

Here I have text file, I want to load it in Haskell, and read it in a List.
import qualified System.Environment
main :: IO ()
main = do
[path] <- System.Environment.getArgs
g <- readFile path
putStr g
But I don't know how to give the address. (Example: the file is /Users/Documents/Programming/test.txt)
After I load this Haskell file:
*Main> main -- How can I write the address?

Under :help, you can see documentation for the :main command:
:main [<arguments> ...] run the main function with the given arguments
Example:
ghci> :main /Users/Documents/Programming/test.txt
...
contents of test.txt
...

Related

how to list the functions exported by a Haskell module from an .hs script?

I am aware of this thread and the agreed-upon ghci :browse command, but I am looking for something similar to run from a script.hs file:
Say I have a module that I can import into my script.hs. How do I then view the list of functions I have just gained access to?
What I've settled on for now
Adapting this thread that suggests the now-deprecated ghc-mod command-line program, I am
calling the terminal command ghc -e ':browse <module, e.g. Data.List>'
from my script.hs using Shelly.
My full script:
#!/usr/bin/env runghc
{-# LANGUAGE OverloadedStrings #-}
import Safe (headDef)
import Shelly
import System.Environment (getArgs)
import qualified Data.Text as T
mdl :: IO String
mdl = getArgs >>= return . headDef "Data.List"
runShelly :: String -> IO ()
runShelly mdl = shelly $ silently $ do
out <- run "ghc" ["-e", T.pack (":browse " ++ mdl)]
let lns = T.lines out
liftIO $ mapM_ (putStrLn .T.unpack) $ lns
main :: IO ()
main = mdl >>= runShelly
This way I can pass the module name on the command line as <script> <module> and get back the functions, one per line. It defaults to Data.List if I pass no arguments.
So that's a solution, but surely there must be handier introspection facilities than this?

How can I test a program reading from stdin in GHCi?

My program has a bug I want to see within GHCi:
$ ./my-program < ./my-data
Prelude.foldl1: empty list
I tried changing stdin or getLine in GHCi but it doesn't seem to affect the getLine my program uses, even if I load afterwards:
$ ghci
Prelude> import System.IO
Prelude System.IO> getLine <- fmap hGetLine $ openFile "my-data" ReadMode
:l "my-program.hs"
:main
Do I need to rewrite all my IOs to take an explicit handle to be able to test them in GHCi?
You can try wrapping your program in something like this (tested, working code):
import qualified System.IO
import qualified GHC.IO.Handle
filename = "/tmp/myfilename"
main = do
h <- System.IO.openFile filename System.IO.ReadMode
old_stdin <- GHC.IO.Handle.hDuplicate System.IO.stdin
GHC.IO.Handle.hDuplicateTo h System.IO.stdin
System.IO.hClose h
realMain
GHC.IO.Handle.hDuplicateTo old_stdin System.IO.stdin
realMain = ...
It should also be possible to define a user-defined GHCi command that does this for any GHCi command, but I haven't tried yet. See here for someone's .ghci that redirects command's stdout with a user-defined :redir command.
I think you want:
ghci> :set args YOUR_ARG
ghci> main
Or
ghci> :main YOUR_ARG
See here: How to set a program's command line arguments for GHCi?

Input arguments using getArgs returns nothing

I am trying to understand getArgs but I am getting a weird behavior that I am not understanding. Here is my program:
getMyArgs :: IO [String]
getMyArgs =do
x <- getArgs
return x
I run this and get:
*Main> hello <- getMyArgs
*Main>
Why doesn't it return my argument passed? I tried to put in a " show() " but that turns it into a String instead of a [String]
getMyArgs :: IO [String]
getMyArgs =do
x <- getArgs
return x
The do notation desugars to:
getMyArgs :: IO [String]
getMyArgs = getArgs >>= \x -> return x
Using the right identity we can rewrite this to:
getMyArgs :: IO [String]
getMyArgs = getArgs
So you've just defined a new name for getArgs. Now why does getArgs not show your program arguments? Well it appears you didn't provide any program arguments. In the interpreter it can be tricky to provide arguments - one way is to :set them:
Prelude> :set args hello world
Prelude> import System.Environment
Prelude System.Environment> getArgs
["hello","world"]
EDIT: Oh you might be looking to print the value you bound. Consider:
Prelude System.Environment> hello <- getArgs
Prelude System.Environment> print hello
["hello","world"]
Thanks to #4castle for this observation.
Assume your Haskell program is compiled to an executable foo. When you call your program, you want to pass some runtime arguments to your program eg foo param1 param2 . Depending on the values of param1 and param2 you will take different actions in your program.
Now with the getArgs function you get access to these parameters in your Haskell program.
In GHCi this argument passing can be simulated. Either with the :set args paarm1 param2 command as shown in the answer of Thomas M. DuBuisson
or you call your main program in GHCI with :main param1 param2 .
In both scenarios getEnv will return IO ["param1", "param2"]

Haskell: parse error on input `import'

I am trying to recreate the output of this Haskell code:
forM_ = flip mapM_
import Control.Monad.Cont
main = do
forM_ [1..3] $ \i -> do
print i
forM_ [7..9] $ \j -> do
print j
withBreak $ \break ->
forM_ [1..] $ \_ -> do
p "loop"
break ()
where
withBreak = (`runContT` return) . callCC
p = liftIO . putStrLn
The expected output is as follows:
$ runhaskell for.hs
1
2
3
7
8
9
loop
But I am getting the following error:
Test4.hs:2:1: parse error on input `import'
Any ideas about what is going wrong?
Test4.hs:2:1: parse error on input `import'
The error points to the second line of your file. Quoting the first two lines:
forM_ = flip mapM_
import Control.Monad.Cont
The problem is that an import declaration must be at the beginning of a module, before any definitions (the only things that can come before an import are language pragmas, such as those used to enable GHC extensions, and the module declaration). In your case, the first line of the file is a definition, and so the misplaced import declaration in the second line leads to a parse error. Since that first line wasn't actually part of the code snippet in the post you linked to, you can simply delete it.

How to dynamically call a function which defined in multiple modules in the same signature

I've defined a lot of functions (say, 100+), each of which do a specific work but with the same signature. That is something like:
module R001 (run) where run = <do-...>
module R002 (run) where run = <do-...>
What I wanna do is to provide the actual 'run' as user input, such that:
main = do
runWith $ read $ getLine
where
runWith :: Int -> IO ()
runWith n = R<n-padded-with-0>.run
Currently, I import all modules qualified, and put all the run's into a list of [Maybe (IO())], so this works:
runWith n = case Rs !! (read $ getLine) of
Just run -> run
Nothing -> undefined
But as the n grows, I have to continously maintain a big list.
Is there any way I can define the big list using TemplateHaskell, or just load the corresponding module as needed at runtime without having to seperate each module into different shared libraries.
Based on epsilonhalbe's answer, I did some research:
import R1 (run1)
import R2 (run2)
test = $(functionExtractor "^run")
main :: IO ()
main = do
putStrLn $ show $ length $ test
run1 -- remove on second attempt
run2 -- remove on second attempt
This block of code prints 2 following the results of run1 and run2. If I remove the last two lines, it just prints 0. It seems that functions imported but not referenced won't be extracted ...
I once had a similar problem haskell load module in list maybe this helps.
You can create a list of functions with regexp and choose a function by userinput from that list.
I don't know if you have to import all "runs" qualified by hand or if you can
import R*.hs (run)
i would rather write one file with run1 = …, run2 = … and generate a list of all runs and a function chooser function which takes a function from a list of functions with the same type signature.
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.Extract
import myRunFunctions
main = do
let listOfRuns = $(functionExtractor "^run")
putStrLn "please choose a run"
putStrLn $ show listOfRuns
let run = runWith $ read $ getLine
run
where
runWith n = listOfRuns !! n
Attention: I have not run this code this is just a stream of thought put in haskell syntax
i hope this is helpful
After edit:
In my example i wrote all run* in one file and there i generated the list of all run functions, which worked instantly - have a look at my Nucleotide Project especially the files Rules.hs and Nucleotide.hs.
Runs.hs
module Runs where
import Language.Haskell.Extract
listOfRuns = map snd $(functionExtractor "^run")
run1 = …
run2 = …
Main.hs
import Runs
main = do
putStrLn "please choose a run"
putStrLn $ show listOfRuns
let run = runWith $ read $ getLine
run
where
runWith n = listOfRuns !! n
happy to be helpful
Is it absolutely critical that the different run functions live in different modules? If you can put them all in one module, you could make run be a function of an Int (or Integer if you prefer).
module AllMyCircuits where
run 0 = {- do blah blah blah -}
run 1 = {- do blah blah blah -}
run 2 = {- do yikes -}
module Main where
import AllMyCircuits
main = readLn >>= run

Resources