Haskell error on text file as input on Mac - macos

I have a Main.hs file with two functions.
Module Main where
import Data.List
main :: IO()
main = interact reverse
functionThatWorks = putStrLn "Ajax"
After I set the directory and load Main.hs I have no problem with calling functionThatWorks.
Except when I want to take a text file as input like so:
Main<in.txt or ./Main<in.txt
I get an error saying 'parse error on input 'in' '
Does anyone know I can make this work in the Terminal?
p.s. I use a Mac.

Unfortunately ghci doesn't understand input redirection like the shell does.
I would suggest running your program with runhaskell:
runhaskell Main.hs < in.txt

Related

How can I store "image lookup -v address" result inside a variable?

I am able to symbolicate symbol address through following lldb command:
image lookup --address $SYMBOL_ADDRRESS
But while writing a shell script to parse, I am not able to find a way to store the output of above command into a variable or file.
First off, if your script's job is mostly about driving lldb and you happen to know Python, you will be much happier using the lldb module in Python, where you can drive the debugger directly, than getting lldb to produce text output which you parse in the shell script.
The lldb Python module provides API's like SBTarget.ResolveSymbolContextForAddress, which runs the same lookup as image lookup --address but returns the result as a Python lldb.SBSymbolContext object, which you can either query for module/file/line etc using API's on the object. So getting bits of info out of this result will be easier with the lldd API's.
But if you have to use a shell script, then the easiest thing is probably to write the command output to a file and read that back into the shell script. lldb doesn't have generic support for tee-ing command output into a log file yet, but the lldb Python module allows you to run command-line commands and programmatically capture the output.
So you can do it easily from lldb's Python script interpreter:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> result = lldb.SBCommandReturnObject()
>>> lldb.debugger.GetCommandInterpreter().HandleCommand("image lookup -va $pc", result)
2
>>> fh = open("/tmp/out.txt", "w")
>>> fh.write(result.GetOutput())
>>> fh.close()
>>> quit
(lldb) plat shell cat /tmp/out.txt
Address: foo[0x0000000100003f6f] (foo.__TEXT.__text + 15)
Summary: foo`main + 15 at foo.c:6:3
Module: file = "/tmp/foo", arch = "x86_64"
CompileUnit: id = {0x00000000}, file = "/tmp/foo.c", language = "c99"
Function: id = {0x7fffffff00000032}, name = "main", range = [0x0000000100003f60-0x0000000100003f8a)
FuncType: id = {0x7fffffff00000032}, byte-size = 0, decl = foo.c:4, compiler_type = "int (void)"
Blocks: id = {0x7fffffff00000032}, range = [0x100003f60-0x100003f8a)
LineEntry: [0x0000000100003f6f-0x0000000100003f82): /tmp/foo.c:6:3
Symbol: id = {0x00000005}, range = [0x0000000100003f60-0x0000000100003f8a), name="main"
You can also write a lldb command in Python that wraps this bit of business, which would make it easier to use. Details on that are here:
https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function
You could even do a hybrid approach, and make all the lldb work you want to do a custom Python command. That would allow you to use the lldb Python API's to get what info you needed and write it out in whatever format is convenient for you, and would simplify the lldb invocation in your shell script and facilitate recovering the information lldb provided...

How to make a change to the source code in Haskell using GHCi?

I am new to Haskell and am using GHCi to edit and run Haskell files. For some reason, I am not able to edit the source code of the file. The behavior I am getting is extremely odd.
Below is a screenshot of what is happening. I am loading the file lec3.hs and am attempting to edit this file to add the following function: myfun = \w -> not w. For some reason, this function successfully runs when I call it immediately after: myfun False. I do not need to reload the file.
It is clear that the function is not being added to the source code. When I reload the file, I am getting an error stating that myfun does not exist.
Could someone help me understand why GHCi is behaving this way, and how to fix such behaviour? I have already spent an hour trying to figure this out. I would sincerely appreciate any help.
Typing things into GHCi isn't supposed to add them to the source. But if you have loaded a file into GHCi you can edit it using the :e command, and when you close the editor it will be automatically reloaded.
You can use :e filename.hs if you are dealing with more than one file and you need to specify.
Generally it's easier to work in a separate editor and just reload into GHCi with :r, but :e is occasionally useful.
To answer
Is it possible to edit a .hs file from GHCi?
It technically speaking is possible, since Haskell has like any other language file-IO operations. Concretely, appendFile allows you to add content to a file.
$ cat >> Foo.hs # Creating a simple Haskell file
foo :: Int
foo = 3
$ ghci Foo.hs
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/sagemuej/.ghc/ghci.conf
Loaded GHCi configuration from /home/sagemuej/.ghci
[1 of 1] Compiling Main ( Foo.hs, interpreted )
Ok, one module loaded.
*Main> foo
3
*Main> appendFile "Foo.hs" $ "myfun = \\w -> not w"
*Main> :r
[1 of 1] Compiling Main ( Foo.hs, interpreted )
Ok, one module loaded.
*Main> myfun False
True
But this really is not a good way to edit files. It makes much more sense to have two windows open, one with a text editor and one with the REPL, i.e. with GHCi. It can be either two completely separate OS windows, or two sub-windows of your IDE or whatever, but in either case GHCi will be used only for evaluation and one-line prototyping, not for actually adding/editing code. (The one-line prototypes can be copy&pasted into the editor, if it helps.)

File name does not match module name

Newbie playing with haskell stack scripting and turtle.
Created a folder stack-scripts. Thought if it looks good, then I'll create some haskell utils for me to replace bash scripts.
Created a file named turtle.hs with following text:
#!/usr/bin/env stack
-- stack --resolver lts-11.2 script
{-# LANGUAGE OverloadedStrings #-}
import Turtle
main = echo "Hello!"
made the chmod +x turtle.hs and tried to execute it.
Got the following error message:
turtle.hs:1:1: error:
File name does not match module name:
Saw: `Main'
Expected: `Turtle'
|
1 | #!/usr/bin/env stack
| ^
It does what it should if I rename turtle.hs to turtle.sh. But then I have no syntax highlighting for haskell.
Also it works if I rename it to something-other.hs. But then Haskero (VSCode) complains about import Turtle line: Couldn't guess that module name. Does it exist?
What I'm missing here? Running in git bash on Windows.
Apparently you need to give the script a different name as the module name in which the code runs, will automatically be derived from it and now it will conflict with the imported Turtle module. Renaming it to turtlescript.hs and then
#!/usr/bin/env stack
-- stack --resolver lts-11.2 script --package turtle
{-# LANGUAGE OverloadedStrings #-}
import Turtle
main :: IO ()
main = echo "Hello!"
worked for me.

How to get the path for openFile in Haskell?

I have the following program which throws a runtime exception:
import System.IO
main :: IO ()
main = do
handle <- openFile "palindrome.txt" ReadMode
input <- hGetContents handle
hClose handle
It type checks, but whenever I try to run main, I'll get an error:
What am I doing wrong?
Your current program uses a relative path. As such, the file must be in the same directory where you started GHCi. Given that your workspace is $HOME/Desktop/Haskell, it probably checks only for $HOME/Desktop/Haskell/palindrome.txt. If you want to use the palindrome.txt in $HOME/Desktop/Haskell/u03/3-1/`, you need to either use the absolute path in your code, or run GHCi in that directory.
Note that you can change the current directory in GHCi with :cd, so the following commands in GHCi should work:
Prelude> :cd /path/to/your/directory
Prelude> :l palindrom-a.hs
*Main> :main

Haskell Noob In Need of Assistance

This is a bit long, so bear with me!
I'm having a bit of trouble working with a Haskell program, that I have to use as part of a uni project. For reference, it's Casper.
So, you're supposed to execute a script, which is actually a Bash script to invoke Hugs interpreter like this:
exec $HUGSBIN/hugs $HUGSARGS +p"Casper> " $FILES
Where $FILES points to a Main.lhs file.
After this, I need to invoke a function "compile" with a path to a file, in the interpreter.
I need to perform the above in a scripted manner. I need this automated because I'm writing a program that will call on Casper in the background.
So I compiled the .lhs file. Now I want to execute the "compile" function but I have no idea how this is done. I try:
./Main compile <a path>
from the command line but it returns me an error about a file "test" not found. Upon investigation, I see these lines in the Main.lhs file:
>main :: String -> IO()
>main = compile "test"
>compile :: String -> IO()
>compile s = catch (compile0 False s) handler
[...snipped]
The 2nd line solves this question. Now my question is, how do I invoke the "compile" function and pass a path to it after I have compiled main.lhs? From the interpreter, I just type "compile " and it works, but I can't get the same to work after compiling the main.lhs and executing from the command line? Any ideas why? Is there any way I can script Hugs if all else fails?
Thank you for any assistance!
You may access the command-line arguments passed to a Haskell program via getArgs. For example, it sounds like you want a main function that does something like this:
>main = do
> args <- getArgs
> case args of
> [] -> putStrLn "What file did you want me to compile?"
> [filename] -> compile filename
> _ -> putStrLn "I only compile one file at a time."
Modify to taste.
Replace main with
main = getArgs >>= \(arg1:_) -> compile arg1
This will pass the first command line argument (arg1) to compile instead of "test", and ignore the rest (_). You may need to add
import System
or
import System.Environment
I can't remember what is needed in hugs for this.

Resources