-2

In natural language it is quite common to have quotation marks within quotation marks, as in, for example:

(1) "This sentence is not a "sentence" "

(2) "‘S’ is true in language L iff S"

(2) is in fact important for any Tarskian truth-definition (Tarski argued the truth of every instance of (2) was necessary for the material adequacy of a truth definition).

Other examples arise in the study of paradoxes; famously, in Quine's paradox we are led to consider (3):

(3) "The statement "'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation" is false"

I am interested in how quotations within quotations can be implemented in Haskell. What I want to know is how, in Haskell, with appropriate technical trickery, we can represent (1)-(3) as they are written above and as they would appear in a book (i.e, not modified orthographically in any way), without receiving an error message.

A simple type search for (3), :t ("The statement "'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation" is false") yields (no pun intended!)

<interactive>:1:18: error:
• Syntax error on 'yields
  Perhaps you intended to use TemplateHaskell or TemplateHaskellQuotes
• In the Template Haskell quotation 'yields
duplode
  • 33,731
  • 7
  • 79
  • 150
user65526
  • 685
  • 6
  • 19
  • 1
    You only need to *escape* the quotations, so `"The statement \"'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation\" is false"` – Willem Van Onsem Mar 15 '18 at 11:02
  • What is the \ operator doing in this case? – user65526 Mar 15 '18 at 11:05
  • 3
    it is not an operator. I think you interpret strings a bit too much like ordinary Haskell code. This is a string literal. String literals have escaping for some characters that can not be added straight away: like quotation marks, but also new lines, tabs, unicode, etc. – Willem Van Onsem Mar 15 '18 at 11:10
  • In any case, I don't find this very convincing: if we are interested in sentences such as (3) we are interested in them as they are, and thus it would be preferable to present them as they are. Perhaps you could claim (3) IS really to be analysed as `"The statement \"'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation\" is false"`. But I'm not so sure about this. I have edited my question to take into account my worry here. – user65526 Mar 15 '18 at 11:11
  • no, since that would make it hard or perhaps even impossible to write a unambiguous lexer and parser, and even if we can, then it could result in a computationally very expensive compiler: it could mean that we would have to backtrack over all possible interpretations. Furthermore a good programming language denotes things that are different in a different way. Now the quotation marks (`"`) are *not* part of the string. Escaped ones on the other hand are. So for a programmer it is clear where the string starts and where it ends. Most people get used to escaping quite fast. – Willem Van Onsem Mar 15 '18 at 11:17
  • Thanks. :) Do you mean it would be strictly speaking impossible, or just a pain in the neck? Mathematically, there are many examples of languages which allow self reference and quotation within quotation, so I can't see it should be impossible. Perhaps if implemented on a small scale it wouldn't be such a pain. Interested to know what you think. – user65526 Mar 15 '18 at 11:19
  • We couldn't, for example have an operator which applies to the result of `putStrLn (show "I said \"hello\".")`, taking out the two occurrences of \ ? – user65526 Mar 15 '18 at 11:23
  • Probably you are looking for [raw string literals](https://en.wikipedia.org/wiki/String_literal#Raw_strings). They do not exist in Haskell – max630 Mar 15 '18 at 11:27
  • 2
    @user65526: you are probably confusing *strings* at the *representation* of strings. In fact if we write `"foo \"bar\" qux"`. We wrote a string that *contains* no backslashes, it does not contain the outer quotes. If you print that string, you get `foo "bar" qux`. The point is that the *representation* of a string literal is something different then what the string contains. – Willem Van Onsem Mar 15 '18 at 11:30
  • Hang on a second. Couldn't you just declare/create a new type, which is the type of `"The statement "'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation" is false")` and more generally the type of any quotation that includes a quotation? Would that be literally impossible? Btw, when I print `"foo \"bar\" qux"` (that is, when I put in `print "foo \"bar\" qux"`), I get `"foo \"bar\" qux"` – user65526 Mar 15 '18 at 11:33
  • The bottom line is this: I want to be able to have `"The statement "'yields falsehood when preceded by its quotation' yields falsehood when preceded by its quotation" is false"`, exactly as you would see it in a book. It's still unclear to me whether this is strictly impossible, or just a real pain to implement. – user65526 Mar 15 '18 at 11:35
  • 3
    @user65526 https://stackoverflow.com/questions/19288652/difference-between-print-and-putstrln-in-haskell - dont use print for strings :) then you dont get leading/trailing " – Patrick Artner Mar 15 '18 at 11:53
  • When I don't use `print` (i.e, when I just put in `"foo \"bar\" qux"` to GHCi, I still get `"foo \"bar\" qux"` and not, as was suggested above `foo "bar" qux`. In any case, this does not answer my question. – user65526 Mar 15 '18 at 11:59
  • 2
    @user65526 Try `putStrLn "foo \"bar\" qux"`; that renders to the terminal the characters actually contained in the string. Just typing `"foo \"bar\" qux"` at the GHCI prompt uses `show` to render it, which is for showing you the representation of the string as Haskell syntax (so it has to use backslashes to escape the quotes). `print` also uses `show` internally. – Ben Mar 15 '18 at 12:24
  • That works, thanks.Ah, and I see it solves my problem. So the solution is to use escape brackets as suggested, and put `putStrLn ` before the result. Due to being a Haskell novice, I didn't realise that this is what was being suggested above. Thanks for all the help :) – user65526 Mar 15 '18 at 12:25
  • The title is overly ambitious. I suggest "representing strings with embedded quotes in Haskell". – n. m. could be an AI Mar 15 '18 at 12:36
  • Thanks, I'll change it :). Feel really sad that it was downvoted: I'd like to know why (I don't know whether that is possible). I just didn't understand and needed help :) – user65526 Mar 15 '18 at 12:37
  • Is it possible to be supplied with a reason why my question was downvoted, and whether the question, as it currently stands, is worthy of a downvote? – user65526 Mar 15 '18 at 14:28
  • 1
    Though I didn't downvote, my guess would be that the downvoters felt that you should have found the answer by searching. A search for `quote in string haskell` brings quite a few relevant results, though few of the questions found in this way state the problem directly like yours does (most are some variation of "`show` for strings is broken, what to do?"). By the way, while downvotes can be useful food for thought, don't let them discourage you -- after all, sometimes it's just that [someone has lost their keys](https://meta.stackexchange.com/a/215397/242059) :) – duplode Mar 16 '18 at 07:34
  • (Ironically, I have just violated the Manual of Style by using code formatting for a quote, as if I had written `"quote in string haskell"` instead it wouldn't be entirely clear whether the quotes should be included in the search engine input or not...) – duplode Mar 16 '18 at 07:36

2 Answers2

3

This answer will mostly repeat what is said in the comments (and in your own answer), but with some elaboration that might be useful.

In what follows, I will abuse keyboard input formatting, as in case, when I want to talk about a string as it really is. You may take "as it really is" to mean a certain sequence of bytes in memory or something more Platonic -- feel free to pick your favourite ontology. What matters is that, if I want to refer to case in a Haskell program, I need some way to specify I'm really talking about a string, as Haskell source code is literally a string of characters which is interpreted in a certain manner -- and, in particular, in that interpretation case would be taken as a keyword introducing a case-statement. The solution adopted by Haskell syntax is using double quotes to introduce string literals, so that "case" represents case.

That's all well and good, but what about This sentence is not a "sentence"? The problem is that Haskell syntax confiscates, among others, the character ", giving it special meaning, which means "This sentence is not a "sentence"" doesn't actually represent This sentence is not a "sentence" (rather, it represents This sentence is not a applied, like a function, to a variable called sentence and the empty string -- which is approximately always nonsense). The solution to this problem is confiscating \ in order to use it as an escape character which, when used within a string literal, indicates the following character should be taken literally, and not according to its usual role in Haskell syntax (that is not the only way \ is used as an escape character, but let's not get bogged down in detail). That being so, This sentence is not a "sentence" is represented by "This sentence is not a \"sentence\"", and all is well in the World.

All of the above probably is, after the long discussion in the comments, very obvious. There are a few interesting things to add, though, about putStrLn, show and print. Starting with putStrLn, its role can be abstractly described as drawing in your screen something that looks sufficiently like how you would represent a string if you weren't concerned about the mundane constraints of Haskell syntax. There is no fundamental difference between putStrLn and an hypothetical cartoonifyStrLn, which would draw a pink Comic Sans string all over your desktop, or even a seeStrLn, which would plant a visual impression of the string directly in your retina. The point is that putStrLn "This sentence is not a \"sentence\"" represents This sentence is not a "sentence" in a way that is completely external to Haskell. This fact is, fortunately enough, expressed by the type system:

GHCi> -- Actually a string.
GHCi> :t "This sentence is not a \"sentence\""
"This sentence is not a \"sentence\"" :: [Char]
GHCi> -- Note how there won't be any mention of String (or [Char]).
GHCi> :t putStrLn "This sentence is not a \"sentence\""
putStrLn "This sentence is not a \"sentence\"" :: IO ()

Values with IO in their types stand in for things that are, in part or wholly, external to Haskell. IO makes it possible to refer to and make use of such things without losing track of this crucial fact about them.

The show function produces string -- or, more precisely, String -- representations of Haskell values

GHCi> show 99
"99"
GHCi> show (Just 99)
"Just 99"

That however, is an incomplete description of what show does. The String it produces is supposed to represent, as a string literal, a valid representation of the value it is given according to Haskell syntax. That is why showing a String produces a string with extra quotes tacked on...

GHCi> show "case"
"\"case\""

... not to mention all the extra backslashes:

GHCi> show "This sentence is not a \"sentence\""
"\"This sentence is not a \\\"sentence\\\"\""

As for print, it is just show followed by putStrLn, so it tends to do what you expect for most types...

GHCi> print 99
99
GHCi> print (Just 99)
Just 99

... but not for Strings -- in their case, you should just use putStrLn instead:

GHCi> print "This sentence is not a \"sentence\""
"This sentence is not a \"sentence\""

P.S.: Possibly interesting extra reading about technicalities: How to convert Unicode Escape Sequence to Unicode String in Haskell and Semantics of show w.r.t. escape characters.

P.P.S.: I welcome criticism of my usage of quotation in this answer.

duplode
  • 33,731
  • 7
  • 79
  • 150
1

As had been initially hinted in a comment below the question, but which was not clear to me at the time (although it may have been utterly obvious to others), there is a simple way of representing (1)-(3) above using \ and putStrLn. We just have to use the following code:

putStrLn "This sentence is not a \"sentence\" "
This sentence is not a "sentence" 

putStrLn "\"S\" is true in language L iff S"
"S" is true in language L iff S

putStrLn "The statement \"'yields falsehood when preceded by its quotation' 
yields falsehood when preceded by its quotation\" is false"
The statement "'yields falsehood when preceded by its quotation' yields 
falsehood when preceded by its quotation" is false
user65526
  • 685
  • 6
  • 19