New line indentation Haskell [duplicate] - string

This question already has answers here:
How can I print a newline properly in Haskell?
(2 answers)
Closed 6 years ago.
I am a complete novice in Haskell and have the following question:
I intend to create the function, which puts three Strings on different lines. Here is the code:
onThreeLines :: String -> String -> String -> String
onThreeLines a b c = a++"\n"++b++"\n"++c
Here is what I run:
onThreeLines "Life" "is" "wonderful"
And what I get:
"Life\nis\nwonderful"
I have also tried the following character, but it doesn't work as well.
"'\n'"

Your function works. If you’re running this in GHCi or using print, you might be confused by the fact that it calls show on the result of your computation, which formats a value as a Haskell term for debugging. For strings, that means including quotes and escapes.
putStrLn (onThreeLines "Life" "is" "wonderful") should do exactly what you expect.

Executing it like this should make it work:
main :: IO ()
main = putStrLn $ onThreeLines "hello" "world" "test"
Executing the program, I get:
$ ./test.hs
hello
world
test
The reason you are getting "Life\nis\nwonderful" is because the Show instance is being used for displaying which will escape the newline.
λ> putStrLn "hello\nworld"
hello
world
λ> print "hello\nworld"
"hello\nworld"
Note that print uses the Show instance for displaying.

There's nothing wrong with your function. "Life\nis\nwonderful" is the resulting String you want. Just remember that if you want the newlines rendered correctly, pass it to a function like putStrLn
putStrLn (onThreeLines "Life" "is" "wonderful")
Also, be sure to check out the unlines function which concatenates a list of strings, separating each element with a newline character.

Related

Writing newlines to files

How can I write a string that contains newlines ("\n") to a file so that each string is on a new line in the file?
I have an accumulator function that iterates over some data and incrementally constructs a string (that contains information) for each element of the data. I don't want to write to the file every step so I'm appending the strings in each step. I do this so I can write the string in one time and limit the amount of IO.
Adding a newline to the string via str ++ "\n" doesn't work, hPrint h str will just print "\n" instead of starting on a new line.
I've tried accumulating a list of strings, instead of one big string, and iterating over the list and printing each string via hPrint. This works for the newlines but it also prints the quotation marks around each string on every line.
Don't use hPrint to write the strings to the file. Just like regular print it outputs the result of show, which produces a debugging-friendly version of the string with control characters and line endings escaped (and the surrounding quotes).
Use hPutStr or hPutStrLn instead. They will write the string to the file as-is (well, the latter adds a newline at the end).
The probably idiomatic solution to what you try to do is to simply aggregate the resulting strings in a list. Then, use the unlines prelude function which has the signature unlines :: [String] -> String and does your \n business for you.
Then, writing the string to disk can be done with help of writeFile which has the signature: writeFile :: FilePath -> String -> IO ().
Haskell is lazy. As such, it sometimes helps to think of Haskell lists as enumerators (C# like IEnumerable). This means here, that trying to compute line wise, then build the string manually and write it line by line is not really necessary. Just as readFile works lazily, so then does e.g. lines. In other words, you gain nothing if you try to "optimize" code which looks in its genuine form similar to this:
main = do
input <- readFile "infile"
writeFile "outfile" ((unlines . process) (lines input))
where
process inputLines = -- whatever you do

Haskell Exception: Prelude.read: no parse

I am new to Haskell, kinda 2 days since I study Haskell, and I want to do a project with files. I did it already in c++ and now I want to do it in Haskell too.
A little part of project is about a library, where I can register a book and a person. Now I want to put book code into a file.txt but to store it as int, not as String, because I have to search and compare this code , with other codes later, and will be easier to compare.
Here is my code, and I receive the following error *** Exception: Prelude.read: no parse. Does anyone know how to solve this please?
import System.IO
main = do
putStrLn "Please put book details"
putStr "Code: "
code <- getLine
let code1 = read code
appendFile "book.txt" ("Cod:" ++ code1 ++ "\n")
This fails since you're attempting to read a String as a String.
read is used to parse a String as an object. To parse a String as a String though, you need to add explicit quotes around the String being parsed. Failing to do so will result in the error that you got. You can test this by adding "s around the input when your program asks for it. It should work.
Do you expect code1 to be an int? If that's the case, there's 2 problems (and a couple ways to solve them) :
You need to tell read what type you want it to parse the string as. To do that, use a type annotation. Add :: int after read code.
Since you can't concatenate an int, change code1 in your last line to (show code1) to convert it back to a String.
The problem with the above way is you're converting from, then to a String. You could avoid any converting by keeping it as a String by skipping the read altogether:
import System.IO
main = do
putStrLn "Please put book details"
putStr "Code: "
code <- getLine
# Check user's input to ensure it's correct.
appendFile "book.txt" ("Cod:" ++ code)

Haskell Printing Strings

How do you print Strings in Haskell with newline characters?
printString :: String -> String -> String -> String
printString s1 s2 s3 = (s1++"\n"++s2++"\n"++s3)
When using the function it prints the entire line including the newline characters as well
As already commented, your code has nothing to do with printing. (It shouldn't have print in it's name either!) Printing is a side-effectful action (it makes something appear observably on your screen!) and hence can't be done without binding in the IO type.
As for the actual task of generating a single three-line string, that is perfectly fulfilled by your suggested solution. "This\nis\ntest" is a three-line string, as witnessed by
Prelude> lines $ printString "This" "is" "test"
["This","is","test"]
The reason why GHCi doesn't actually output three separate lines when you just write
Prelude> "This\nis\ntest"
"This\nis\ntest"
is that the print function that's used for this purpose always guarantees a format that's safe to use again in Haskell code, hence it puts strings in quotes and escapes all tricky characters including newlines.
If you simply want to dump a string to the terminal as-is, use putStrLn instead of print.
Prelude> putStrLn $ printString "This" "is" "test"
This
is
test
In ghci, you can just type
putStrLn "line1\nline2"
If you want to write a program to do this, you need to make sure that putStrLn runs in the IO monad, for instance, by putting it in main
main = do
<do stuff>
putStrLn "line1\nline2"
<do other stuff>
Your printString function does not print a string, it simply returns a string. Because you're running this in GHCi, it gets printed out. But it's GHCi that's printing it; your function itself prints nothing.
If you were to compile some code that calls printString, you would discover that nothing gets printed.
By default, GHCi prints stuff as expressions. If you want to write the string to the console unaltered, you need to use putStrLn, as the other answers suggest. Compare:
Prelude> print "1\n2"
"1\n2"
Prelude> putStrLn "1\n2"
1
2
Basically when you write an expression in GHCi, it automatically calls print on the result if possible. Because if you're executing something, you probably want to see what the result was. Compiled code doesn't do this; it only prints what you explicitly tell it to.

Summing up Haskell output lines

I want to write a programm which would print out only one integer after applying some functions to the lines in text file, so far I have :
main = do
c <- getLine
let plot = plots (split ',' (change c))
print plot
main
where plots, split and change are the functions that convert input from string to int removing non-integer chars and then applying some calculations, the problem is that my input file has a lot of lines and I only managed to write a program which applies those functions to every line separately and prints out the result of every line,(I get as much output lines as there are input lines), but I want that this programm would sum up the results of every line and would print out only that number, where should I start or maybe somebody knows the solution? I am new in Haskell so please don't judge :/
Assuming that your conversion functions work for multi-line inputs, you can probably get away with simply replacing getLine with getContents and removing the recursive call to main. Although if you actually want to read a file, using readFile is probably cleaner than using getContents, since the latter is typically used for reading from the command line.
To expand upon what Paul wrote, getContents is like getLine, but it gives you the entire file in a single string. You can then get a list of lines using lines. For example:
main :: IO ()
main = do
contents <- getContents
print (lines contents)
When given the file
Haskell
is
neat!
will print ["Haskell","is","neat!"]. From here, you can map your line-handling function over that list to get a list of integers, and finally print (sum resultList).

Split a string while keeping delimiters Haskell

Basically I'm trying to split a String into [[String]] and then concat the results back but keeping the delimiters in the resultant list (even repeating in a row).
Something like the below kind of works, but the delimiter gets crunched into one space instead of retaining all three spaces
unwords . map (\x -> "|" ++ x ++"|") . words $ "foo bar"
-- "|foo| |bar|"
Ideally I could get something like:
"|foo|| ||bar|" -- or
"|foo| |bar|"
I just can't figure out how to preserve the delimiter, all the split functions I've seen have dropped the delimiters from the resulting lists, I can write one myself but it seems like something that would be in a standardish library and at this point I'm looking to learn more than the basics which includes getting familiar with more colloquial ways of doing things.
I think I'm looking for some function like:
splitWithDelim :: Char -> String -> [String]
splitWithDelim "foo bar" -- ["foo", " ", " ", " ", "bar"]
or maybe it's best to use regexes here?
You can split a list, keeping delimiters using the keepDelimsL and keepDelimsR functions in the Data.List.Split package, like here:
split (keepDelimsL $ oneOf "xyz") "aazbxyzcxd" == ["aa","zb","x","y","zc","xd"]

Resources