Outputting Haskell GHCi command results to a txt file - haskell

I am new to Haskell.
I am having a really difficult time outputting command results from GHCi to a file. I was wondering if someone can give me a simple explanation on how to do this? The examples I have found online so far seem over complicated.

This post on Reddit describes how to colorize your GHCi output (GHC >= 7.6). Instead of a prettyprinter, you could specify a logging function. For example, add the following to your .ghci.conf:
:{
let logFile = "/home/david/.ghc/ghci.log"
maxLogLength = 1024 -- max length of a single write
logPrint x = appendFile logFile (take maxLogLength (show x) ++ "\n") >> print x
:}
:set -interactive-print=logPrint
This will log GHCi's output to ghci.log.
The logging file must already exist, otherwise appendFile will complain. You'll have to create that manually.
It has to fit in a let statement, otherwise GHCi will reject it. Use :{ :} to add multiline support in GHCi.
Apparently, using :l gets rid of all imports you've made in your ghci.conf, therefore you're limited to Prelude functions. The Reddit post mentions that you can somehow redefine :l, but I don't know anythng about that. (If you know how to do this, you can of course automatically generate the logfile if it doesn't exist.)

Let's suppose you have a function mungeData and you do
ghci> mungeData [1..5]
[5,2,5,2,4,6,7,4,6,78,4,7,5,3,57,7,4,67,4,6,7,4,67,4]
writeFile
You can write this to file like this:
ghci> writeFile "myoutput.txt" (show (mungeData [1..5])
I'd be inclined to write
ghci> writeFile "myoutput.txt" $ show $ mungeData [1..5]
to get rid of a few brackets.
Reading it back in
You could get that back using
ghci> fmap (read::String -> [Int]) $ readFile "myoutput.txt"
One number per line
You could output it a line per number like this:
ghci> writeFile "myoutput'.txt" $ unlines.map show $ mungeData [1..5]
which reads back in as
ghci> fmap (map read.lines::String -> [Int]) $ readFile "myoutput'.txt"

Related

Strange behaviour of `ReadP` with regards to `fmap head`

Consider the following repl session:
λ import Text.ParserCombinators.ReadP
λ x $$ y = readP_to_S x y
-- This auxiliary function makes things tidier.
λ many get $$ "abc"
[("","abc"),("a","bc"),("ab","c"),("abc","")]
-- This is reasonable.
λ fmap head (many get) $$ "abc"
[(*** Exception: Prelude.head: empty list
-- Wut?
λ fmap last (many get) $$ "abc"
[(*** Exception: Prelude.last: empty list
-- This works neither.
λ fmap id (many get) $$ "abc"
[("","abc"),("a","bc"),("ab","c"),("abc","")]
-- The list is there until I try to chop its head!
My questions:
What is happening here?
How can I extract a single (preferably longest) parse result?
P.S. My goal is to construct a parser combinator that greedily returns the repetitive application of a given parser. (get in this instance, but in actuality I have a more involved logic.) Chopping the list of intermediate results is one approach I thought would do, but I am fine with any, except that it is preferable not to convert to ReadS and back.

Automatically reloading variable state into GHCi when re-loading a file

When I'm developing some data analyses pipelines in haskell, it often would be useful to preload variable state into GHCi upon loading.
What I end up doing now is copy and pasting parts of a script line-by-line in emacs just to test and check the output of some intermediate processing. I can't even bulk copy-paste code because the line breaks don't get transferred (at least in emacs Interactive-Haskell mode)
Is there a way to do this?
EDIT: simply loading/reloading a .hs file doesn't do the trick because afaik there's no way to have "<-" bindings at the top level.
I suggest you take a look at foreign-store. It allows you to refer to variables by numbers, which persists through reloads. Here is an example:
λ: :set -XScopedTypeVariables
λ: import Foreign.Store
λ: st <- newStore "example"
Loading package foreign-store-0.2 ... linking ... done.
λ: readStore st
"example"
λ: st
Store 0
λ: :r
Ok, modules loaded: none.
λ: st
<interactive>:8:1:
Not in scope: ‘st’
Perhaps you meant ‘fst’ (imported from Prelude)
λ: Just (st :: Store String) <- lookupStore 0
λ: readStore st
"example"
Alternatively, you can also put all your definitions in a single hs file and only reload that. You can use unsafePerformIO to get around the restriction that you cannot use <- at the top-level. I think that is ok in this case, since your only using it for interactive anyway:
module Example where
import System.IO.Unsafe
example :: String
example = "example"
file :: String
file = unsafePerformIO $ readFile "/tmp/example.hs"
There are two main ways to do this:
Use the :l [filename] GHCi command to reload a file without exiting GHCi.
Write the variables in your ~/.ghci file, which will be loaded when GHCi is opened.
If you don't know what to put into ~/.ghci, here's what I have in mine:
:set prompt "\955 "
:set prompt2 "| "
:def hoogle \x -> return $ ":!hoogle --info \"" ++ x ++ "\""
let f `on` x = \a b -> (f a) `x` (f b)
let break (f,g) = \a -> (f a, f g)

string variable as haskell command

when I do following it works
print [1..5]
and result [1,2,3,4,5]
but why following is not working
let x = "[1..5]"
print x
I want to process a string variable as haskell command. can someone please help me in it.
Note that your second example:
let x = "[1..5]"
print x
works just fine, it just says something different than you intended.
If you wish to consider some string as a valid Haskell expression then you'll need to interpret that string via some Haskell interpreter. The most common interpreter is accessed via the ghc-api. A clean wrapper for the ghc-api is the hint package.
A simple example of using hint is (via ghci):
import Language.Haskell.Interpreter
let x = "[1..5]"
Right result <- runInterpreter $ setImports ["Prelude"] >> eval x
print result
The above code will:
Import an Interpreter module from the hint package
Set a string, x, which is the expression you desire to evaluate
Run the interpreter on the expression
Print the result (which is already a string, so you might prefer putStrLn result).
If you just want to get a list as a string, take advantage of the show function
let x = show [1..5]
print x
Your first answer "works" because function application is right associative, so Haskell evaluates [1..5] to produce the list [1,2,3,4,5] and passes this to the print function.
It looks like you're looking for System.Eval.Haskell.eval or one of its variants. In this case, I believe that
import System.Eval.Haskell
do x <- eval "[1..5]" [] :: IO (Maybe Int List)
putStrLn (if isJust x then "" else show $ fromJust x)
will do what you want.

Haskell - loop over user input

I have a program in haskell that has to read arbitrary lines of input from the user and when the user is finished the accumulated input has to be sent to a function.
In an imperative programming language this would look like this:
content = ''
while True:
line = readLine()
if line == 'q':
break
content += line
func(content)
I find this incredibly difficult to do in haskell so I would like to know if there's an haskell equivalent.
The Haskell equivalent to iteration is recursion. You would also need to work in the IO monad, if you have to read lines of input. The general picture is:
import Control.Monad
main = do
line <- getLine
unless (line == "q") $ do
-- process line
main
If you just want to accumulate all read lines in content, you don't have to do that. Just use getContents which will retrieve (lazily) all user input. Just stop when you see the 'q'. In quite idiomatic Haskell, all reading could be done in a single line of code:
main = mapM_ process . takeWhile (/= "q") . lines =<< getContents
where process line = do -- whatever you like, e.g.
putStrLn line
If you read the first line of code from right to left, it says:
get everything that the user will provide as input (never fear, this is lazy);
split it in lines as it comes;
only take lines as long as they're not equal to "q", stop when you see such a line;
and call process for each line.
If you didn't figure it out already, you need to read carefully a Haskell tutorial!
It's reasonably simple in Haskell. The trickiest part is that you want to accumulate the sequence of user inputs. In an imperative language you use a loop to do this, whereas in Haskell the canonical way is to use a recursive helper function. It would look something like this:
getUserLines :: IO String -- optional type signature
getUserLines = go ""
where go contents = do
line <- getLine
if line == "q"
then return contents
else go (contents ++ line ++ "\n") -- add a newline
This is actually a definition of an IO action which returns a String. Since it is an IO action, you access the returned string using the <- syntax rather than the = assignment syntax. If you want a quick overview, I recommend reading The IO Monad For People Who Simply Don't Care.
You can use this function at the GHCI prompt like this
>>> str <- getUserLines
Hello<Enter> -- user input
World<Enter> -- user input
q<Enter> -- user input
>>> putStrLn str
Hello -- program output
World -- program output
Using pipes-4.0, which is coming out this weekend:
import Pipes
import qualified Pipes.Prelude as P
f :: [String] -> IO ()
f = ??
main = do
contents <- P.toListM (P.stdinLn >-> P.takeWhile (/= "q"))
f contents
That loads all the lines into memory. However, you can also process each line as it is being generated, too:
f :: String -> IO ()
main = runEffect $
for (P.stdinLn >-> P.takeWhile (/= "q")) $ \str -> do
lift (f str)
That will stream the input and never load more than one line into memory.
You could do something like
import Control.Applicative ((<$>))
input <- unlines . takeWhile (/= "q") . lines <$> getContents
Then input would be what the user wrote up until (but not including) the q.

Better data stream reading in Haskell

I am trying to parse an input stream where the first line tells me how many lines of data there are. I'm ending up with the following code, and it works, but I think there is a better way. Is there?
main = do
numCases <- getLine
proc $ read numCases
proc :: Integer -> IO ()
proc numCases
| numCases == 0 = return ()
| otherwise = do
str <- getLine
putStrLn $ findNextPalin str
proc (numCases - 1)
Note: The code solves the Sphere problem https://www.spoj.pl/problems/PALIN/ but I didn't think posting the rest of the code would impact the discussion of what to do here.
Use replicate and sequence_.
main, proc :: IO ()
main = do numCases <- getLine
sequence_ $ replicate (read numCases) proc
proc = do str <- getLine
putStrLn $ findNextPalin str
sequence_ takes a list of actions, and runs them one after the other, in sequence. (Then it throws away the results; if you were interested in the return values from the actions, you'd use sequence.)
replicate n x makes a list of length n, with each element being x. So we use it to build up the list of actions we want to run.
Dave Hinton's answer is correct, but as an aside here's another way of writing the same code:
import Control.Applicative
main = (sequence_ . proc) =<< (read <$> getLine)
proc x = replicate x (putStrLn =<< (findNextPalin <$> getLine))
Just to remind everyone that do blocks aren't necessary! Note that in the above, both =<< and <$> stand in for plain old function application. If you ignore both operators, the code reads exactly the same as similarly-structured pure functions would. I've added some gratuitous parentheses to make things more explicit.
Their purpose is that <$> applies a regular function inside a monad, while =<< does the same but then compresses an extra layer of the monad (e.g., turning IO (IO a) into IO a).
The interesting part of looking at code this way is that you can mostly ignore where the monads and such are; typically there's very few ways to place the "function application" operators to make the types work.
You (and the previous answers) should work harder to divide up the IO from the logic. Make main gather the input and separately (purely, if possible) do the work.
import Control.Monad -- not needed, but cleans some things up
main = do
numCases <- liftM read getLine
lines <- replicateM numCases getLine
let results = map findNextPalin lines
mapM_ putStrLn results
When solving SPOJ problems in Haskell, try not to use standard strings at all. ByteStrings are much faster, and I've found you can usually ignore the number of tests and just run a map over everything but the first line, like so:
{-# OPTIONS_GHC -O2 -optc-O2 #-}
import qualified Data.ByteString.Lazy.Char8 as BS
main :: IO ()
main = do
(l:ls) <- BS.lines `fmap` BS.getContents
mapM_ findNextPalin ls
The SPOJ page in the Haskell Wiki gives a lot of good pointers about how to read Ints from ByteStrings, as well as how to deal with a large quantities of input. It'll help you avoid exceeding the time limit.

Resources