I was trying to get familiar with System.IO and handles. I want to just read a csv file, put a line of comma separated integers into a list, put that list into a list of lists, then put the next line into the list of lists, and so forth until the end of the file. I can read the file, and read a line of the file, but am struggling to make something that will do what I'm trying to do. The csv file, "1.csv" looks like this:
1,2,3,4
4,3,2,1
12,13
The code I have so far is as follows. It finds an error at the line "_ -> x:xs". I'm not used to using case x of at all so I might not be using that right, but it seems like a way to go with this. I know a lot of what I'm doing is wrong, but I'm not really sure how to go further.
import System.IO
xs = []
xss = []
readTheLine = do handle <- openFile "1.csv" ReadMode
x <- hGetChar handle
case x of
'\n' -> xs:xss
_ -> x:xs
'' -> putStrLn xss
main = readTheLine
I'm also pretty sure '' wouldn't signal the end of the file, but not sure what to do here and was trying to show what I'm going for.
I'm learning some Haskell and I came across this small program
reverseLines :: String -> String
reverseLines input =
unlines (map reverse (lines input))
main :: IO ()
main = interact reverseLines
This program will keep asking the user for more input and reverse the input and print it on the screen.
Most of this is straight forward but one thing I can't wrap my head around is why does this function keeps running and ask the user for more input whereas if I just replace the reverseLines function with a function the simply returns some string it will not happen.
This program will stop after one execution:
foo input = "Stops"
main :: IO ()
main = interact foo
Why?
If you look at the source of interact you see this:
interact f = do s <- getContents
putStr (f s)
see the getContents? This is where the magic starts - it will read everything till EOF
Now in Haskell this is lazy-IO which can be bad but here is almost magical - see the string is read lazily and passed to your reverseLines - this one of course will only generate output as soon as it saw \n characters (the lines) and so it seems your program is some kind of REPL.
In the second one you don't consume any of the lazy-string at all so it stops ASAP
As I wrote in the comments you can play with this by either passing content into the program using a file (or echo) and pipes on the terminal:
echo "Hello World\nBye Bye" | runhaskell LazyIO.hs
or using CTRL-D to pass in the EOF yourself.
To get a feeling for it I would play with the functions more - what happens if you use something that needs to see the complete input first (try reverse without the maps)? What happens with words instead of lines, ...?
Have fun!
I have question related Haskell language.i need to store bunch of characters in 2D array.How can i store it??I have characters in 10 X 10 format in text file and i want to store it in 2D character array in haskell language.Please help me as soon as possible..thank you..
Here is the code which i tried and in this code i am trying to store value of x in the list named listofchar::
module TreasureFile where
import System.IO
main = do
hdl <- openFile "map.txt" ReadMode
readbychar hdl
readbychar hdl = do
t <- hIsEOF hdl
if t
then return()
else do
let listofchar=[]
x <- hGetChar hdl
if x =='\n'
then putChar '!'--return()
else listofchar x
readbychar hdl
Try this:
import System.IO
main = do
textContents <- readFile "map.txt"
let map = format textContents
print $ map
format text = lines text
Lets step through this program:
First, readFile reads us the file and binds the contents to textContents.
Next we format the contents by splitting the list every time we encounter a newline delimiter and then remove the eventually remaining empty strings.
Done! Now we can do whatever we want with our "map".
A small note on the side:
It will seem strange that our map will be displayed like this:
["aaaaaaaaaa","bbbbbbbbbbb",..] -- doesn't look like 2D map
which is just syntatic sugar for:
[['a','a','a',..],['b','b','b',..],..] -- looks more like a map now
** old**
Suppose we have a pattern ex. "1101000111001110".
Now I have a pattern to be searched ex. "1101". I am new to Haskell world, I am trying it at my end. I am able to do it in c but need to do it in Haskell.
Given Pattern := "1101000111001110"
Pattern To Be Searched :- "110
Desired Output:-"Pattern Found"`
** New**
import Data.List (isInfixOf)
main = do x <- readFile "read.txt"
putStr x
isSubb :: [Char] -> [Char] -> Bool
isSubb sub str = isInfixOf sub str
This code reads a file named "read", which contains the following string 110100001101. Using isInfixOf you can check the pattern "1101" in the string and result will be True.
But the problem is i am not able to search "1101" in the string present in "read.txt".
I need to compare the "read.txt" string with the user provided string. i.e
one string is their in the file "read.txt"
and second string user will provid (user defined) and we will perform search and find whether user defined string is present in the string present in "read.txt"
Answer to new:
To achieve this, you have to use readLn:
sub <- readLn
readLn accepts input until a \n is encountered and <- binds the result to sub. Watch out that if the input should be a string you have to explicitly type the "s around your string.
Alternatively if you do not feel like typing the quotation marks every time, you can use getLine in place of readLn which has the type IO String which becomes String after being bound to sub
For further information on all functions included in the standard libraries of Haskell see Hoogle. Using Hoogle you can search functions by various criteria and will often find functions which suit your needs.
Answer to old:
Use the isInfixOf function from Data.List to search for the pattern:
import Data.List (isInfixOf)
isInfixOf "1101" "1101000111001110" -- outputs true
It returns true if the first sequence exists in the second and false otherwise.
To read a file and get its contents use readFile:
contents <- readFile "filename.txt"
You will get the whole file as one string, which you can now perform standard functions on.
Outputting "Pattern found" should be trivial then.
Is there any fast way in Haskell to cast an input file like that into corresponding types? For example a function that takes a string and produces a list of Ints? Or do I need to parse it manually using getLine and parse the string?
10.
10.
[4, 3, 2, 1].
[(5,8,'~'), (6,4,'*'), (7,10,'~'), (8,2,'o')].
[4,0,9,4,7,5,7,4,6,4].
[4,10,0,6,6,5,6,5,6,2].
Yes, the read function.
Once you read in the file with readFile for example, you can read each line to convert it to the type you want. You'll have to get rid of the periods first, though. So for example:
main = do
text <- readFile "test.txt"
let cases = lines text
-- to get rid of the periods at the end of each line
strs = map init cases
lastLine = read $ last strs
print $ show (map (+5) lastLine)
This will take your example file and read in a list of Ints from the last line, and the add 5 to the whole list and print it.
If every line were the same type, you could just map read over all the lines to get all of them. If there are different types, like in your example, you'd have to put in some logic to figure out what type is on each line, and then call an appropriate function to deal with that type.
To build on Jeff Burka's answer, here's the specific code you would use for your particular file:
main = do
[l1, l2, l3, l4, l5, l6] <- fmap (map init . lines) $ readFile "myFile.txt"
let myVal :: (Int, Int, [Int], [(Int, Int, Char)], [Int], [Int])
myVal = (read l1, read l2, read l3, read l4, read l5, read l6)
print myVal
This will print out the parsed tuple.
The init part is to get rid of the trailing period you have at the end of each line.