Running this with M 1 will show a new line and a will show the characters "\n" in the ghci output.
Since they are the same characters i would expect the same behaviour.
Any reason why?
data V = M Int
instance Show V where
show m = a
a :: [Char]
a = "\n"
Whenever a value is displayed in GHCi, it uses the Show instance of that object to convert it to human-readable text by applying the show function, then printing the resulting String. In your case, what is happening is:
You have defined the Show instance of V to be a constant "\n", or newline. Thus when GHCi tries to display a value of type V it outputs a newline.
By contrast, the Show instance of String is defined in such a way that for any string s, show s will output the Haskell representation of s. For instance, show "\n" will give a result of "\"\\n\" (i.e. quotation mark, backslash, n, quotation mark). (Try running show "myString" in GHCi and seeing the result for different strings to get an idea of how this works.) Thus when GHCi displays a String, it takes the string (a newline, in your case), converts it to a human-readable format with escape characters using show, and then displays that new string.
Why is show implemented in this convoluted way for strings? I’m not quite sure, but one possibility is disambiguation: show 1 is "1", but show "1" is "\"1\"". When printed to the console, the former is clearly a number, whereas the latter is clearly a string.
Related
I aim to scan a string containing a colon as a division and save both parts of it in a tuple.
For example:
input: "a:b"
output: ("a", "b")
My approach so far keeps getting the error message:
"scanf: bad input at char number 9: looking for ':', found '\n'".
Scanf.bscanf Scanf.Scanning.stdin "%s:%s" (fun x y -> (x,y));;
Additionally, my approach works with integers, I'm confused why it is not working with strings.
Scanf.bscanf Scanf.Scanning.stdin "%d:%d" (fun x y -> (x,y));;
4:3
- : int * int = (4, 3)
The reason for the issue you're seeing is that the first %s is going to keep consuming input until one of the following conditions hold:
a whitespace has been found,
a scanning indication has been encountered,
the end-of-input has been reached.
Note that seeing a colon isn't going to satisfy any of these (if you don't use a scanning indication). This means that the first %s is going to consume everything up to, in your case, the newline character in the input buffer, and then the : is going to fail.
You don't have this same issue for %d:%d because %d isn't going to consume the colon as part of matching an integer.
You can fix this by instead using a format string which will not consume the colon, e.g., %[^:]:%s. You could also use a scanning indication, like so: %s#:%s.
Additionally, your current method won't consume any trailing whitespace in the buffer, which might result in newlines being added to the first element on subsequent use of this, so you might prefer %s#:%s\n to consume the newline.
So, in all,
Scanf.bscanf Scanf.Scanning.stdin "%s#:%s\n" (fun x y -> (x,y));;
The %s specifier is greedy and it will read the string up to whitespace or a scanning indicator. The indicator could be specified using #<indicator> just after the %s specifier, where <indicator> is a single character, e.g.,
let split str =
Scanf.sscanf str "%s#:%s" (fun x y -> x,y)
This will instruct scanf to read everything up to : into the first string, drop : and then read the rest into the second string.
The string specifier %s is eager by default and will swallow all your content until the next space. You need to add a scanning indication(https://ocaml.org/api/Scanf.html#indication) to explain to Scanf.sscanf that you expect the first string to end on the first : :
For instance,
Scanf.sscanf "a:b"
"%s#:%s"
(fun x y -> x,y)
returns "a", "b". Here the scanning indication is the #: specifier just after the first %s specifier. In general, scanning indication are written #c for a character c.
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.
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
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.
I was supposed to write a code in Haskell which calculates the hexadecimal-notation when I have the octal. Unfortunately, I have no Idea how to start and which functions I have to link. Could anyone help me with that?
First read in the octal value (drop the 'o' or other indicator) via readOct. Then, take that Integer and convert it to a hex string using showHex, and decorate as you like.
main = do
octStr <- getLine
let
val :: Integer
(val,_):_ = readOct octStr
hexStr = showHex val ""
putStrLn hexStr
Also, depending on how frequently you do this, you might try and avoid the String type and use either ByteString (with these show like functions) or Text (with these show like functions). Seems octal doesn't get much attention, at least not as much as decimal and hexadecimal.