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.
Related
My function works ok. But I want to use this function with a file's text. The text file has a word before an integer list. How can I do this?
This is the function:
broke :: Integer -> Integer
broke n = pollard 1 2 n 2 2
The contents of the file is:
Word (11,12)
I want to apply the function broke to the first number.
Well this might be kind of a cheat, but the contents of that file is a valid Haskell expression so you could use Read to do it:
import System.IO (readFile)
data Word = Word (Integer,Integer)
deriving (Read)
main = do
contents <- readFile "path/to/file" -- or wherever your file is
let Word (x,y) = read contents
print $ broke x
The reason this works is that deriving (Read) automatically writes a parser for you, so you get the function read :: String -> Word for free. So this technique is only going to work for files whose contents look like Haskell -- otherwise you will need to write your own parser.
This is an excerpt of a file.csv file with some tabular data
John,23,Paris
Alban,28,London
Klaus,27,Berlin
Hans,29,Stockholm
Julian,25,Paris
Jonathan,26,Lyon
Albert,27,London
The column headers for this file would be
firstName, age, city
This file is loaded in ghci like this
𝛌> :m + Data.List Data.Function Data.List.Split
𝛌> contents <- readFile "file.csv"
𝛌> let t = map (splitOn ",") $ lines contents
𝛌> mapM print $ take 3 t
["John","23","Paris"]
["Alban","28","London"]
["Klaus","27","Berlin"]
[(),(),()]
Now, if I want to add a birthYear column to those 3 columns, I can do
𝛌> let getYear str = show $ 2016 - read str
𝛌> let withYear = map (\(x:xs) -> x : xs ++ [getYear (head xs)]) t
𝛌> mapM print $ take 3 withYear
["John","23","Paris","France","1993"]
["Alban","28","London","UK","1988"]
["Klaus","27","Berlin","Germany","1989"]
[(),(),()]
This works well but what bothers me is that the getYear function has type String -> String and as such, type checking is pretty much useless here.
I could easily convert t into a list of tuples like ("John", 23, "Paris") but what about if I have not 3, but 300 features (which is not that uncommon in machine learning problems)?
What would be the best way to deal with different column types? Using tuples? Using maps?
In case of a big number of columns, is there a way to make Haskell infer the column's types? For instance, it would detect that column 2 in the above example is Int, and the others are strings?
Concerning column headers, would there be a way that one could simply access the columns by label instead of by index, so that getYear could be something like 2016 - column['age'] (Python example)?
I'm used to Python's Pandas DataFrames which perform all this stuff automagically, but Haskell looks like it could perform a ton of it natively. Not sure how to do this however as of now.
I am trying to write a list into a file and later on I want to read the file contents into the list as well.
So I have a list like this ["ABC","DEF"]
I have tried things like
hPrint fileHandle listName
This just prints into file "["ABC","DEF"]"
I have tried unlines but that is priniting like "ABC\nDEF\n"
Now in both the cases, I cant read back into proper list. The output file has quotes and because of which when I read, I get like this ["["ABC","DEF"]""] i.e a single string in list.
As I am not succeeding in this, I tried to write the list line by line, I tried to apply a map and the function to write the list k = map (\x -> hPrint fileSLC x) fieldsBefore, it is not doing anything, file is blank. I think if I write everything in separate line, I will be able to read like (lines src) later on.
I know whatever I am doing is wrong but I am writing the code on Haskell for second time only, last time I just a wrote a very a small file reading program. Moving from imperative to functional is not that easy. :(
Try using hPutStrLn and unlines instead of hPrint. The hPrint internally calls show which causes Strings to be quoted and escaped.
hPutStr fileHandle (unlines listName)
Alternatively, use a mapM or a forM. A verbose example is:
forM_ listName $ \string ->
hPutStrLn string
This can be simplified ("eta-contracted", in lambda-calculus terminology) to
forM_ listName hPutStrLn
As you have seen, when you read from a file, you get a String. In order to convert this String into a list, you will need to parse it.
For k = map (\x -> hPrint fileSLC x) fieldsBefore to work, you need to use mapM or mapM_ instead of map.
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
I'm trying to learn Haskell to get used to functional programming languages. I've decided to try a few problems at interviewstreet to start out. I'm having trouble reading from stdin and doing io in general with haskell's lazy io.
Most of the problems have data coming from stdin in the following form:
n
data line 1
data line 2
data line 3
...
data line n
where n is the number of following lines coming from stdin and the next lines are the data.
How do I run my program on each of the n lines one at a time and return the solution to stdout?
I know the stdin input won't be very large but I'm asking about evaluating each line one at a time pretending the input is larger than what can fit in memory just to learn how to use haskell.
You can use interact, in conjunction with lines to process data from stdin one line at a time. Here's an example program that uses interact to access stdin, lines to split the data on each newline, a list comprehension to apply the function perLine to each line of the input, and unlines to put the output from perLine back together again.
main = interact processInput
processInput input = unlines [perLine line | line <- lines input]
perLine line = reverse line -- do whatever you want to 'line' here!
You don't need to worry about the size of the data you're getting over stdin; Haskell's laziness ensures that you only keep the parts you're actually working on in memory at any time.
EDIT: if you still want to work on only the first n lines, you can use the take function in the above example, like this:
processInput input = unlines [perLine line | line <- take 10 (lines input)]
This will terminate the program after the first ten lines have been read and processed.
You can also use a simple recursion:
getMultipleLines :: Int -> IO [String]
getMultipleLines n
| n <= 0 = return []
| otherwise = do
x <- getLine
xs <- getMultipleLines (n-1)
return (x:xs)
And then use it in your main:
main :: IO ()
main = do
line <- getLine
let numLines = read line :: Int
inputs <- getMultipleLines numLines