Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign uptoString behaves unintuitively #657
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
process-bot
Jul 4, 2016
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!
Here is what to expect next, and if anyone wants to comment, keep these things in mind.
process-bot
commented
Jul 4, 2016
|
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it! Here is what to expect next, and if anyone wants to comment, keep these things in mind. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
pdamoc
Jul 4, 2016
Elm's toString behaves closer to Haskell's show. The current behavior allows one to distinguish between the string "Hello" and the value Hello defined in a type like type Greeting = Hello | Hi
If you want toString to not display the extra ", just implement your own version that checks if there are extra " :
toStr v =
let
str = toString v
in
if left 1 str == "\"" then
dropRight 1 (dropLeft 1 str)
else
str
pdamoc
commented
Jul 4, 2016
|
Elm's If you want toStr v =
let
str = toString v
in
if left 1 str == "\"" then
dropRight 1 (dropLeft 1 str)
else
str |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
shmookey
Jul 4, 2016
To follow up from Slack - the closest you're going to get to the behaviour you want is (as @pdamoc suggests) stripping the quotes off yourself.
A function that could tell you at runtime whether or not a value of type a represents a string would not actually help you here. Let's try rewriting your get function, imagining that we have some function isString : a -> Bool
get : Maybe a -> String
get ma = case ma of
Just x -> if isString x
then ???
else toString x
Nothing -> ""How could we fill in the blank? It can't just be x, because the only type the compiler knows for x is a, and it needs String. You still need to call toString, and you still need to strip off the quotes.
If you would like to see some other function of type a -> String that yields an unquoted value when a is a string, what do you propose it would do for other types?
I still say your function is too general. If a type variable appears once in a function signature, you can't do anything with a value of that type because the compiler doesn't know anything about it. toString does, but that's magic. If you need to do anything at all with a value you've explicitly generalised to a - other than combine it with or pass it to another argument typed a in the same signature - you need to introduce some constraints. That's how you express this function "properly".
shmookey
commented
Jul 4, 2016
•
|
To follow up from Slack - the closest you're going to get to the behaviour you want is (as @pdamoc suggests) stripping the quotes off yourself. A function that could tell you at runtime whether or not a value of type get : Maybe a -> String
get ma = case ma of
Just x -> if isString x
then ???
else toString x
Nothing -> ""How could we fill in the blank? It can't just be If you would like to see some other function of type I still say your function is too general. If a type variable appears once in a function signature, you can't do anything with a value of that type because the compiler doesn't know anything about it. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rtfeldman
Jul 4, 2016
Member
This came up in the string interpolation discussion, as toString would have to work as OP expected it to in order for string interpolation to work.
I'm curious - is anyone depending on the current behavior, and couldn't work around such a change with Json.Encode.string? (cc @eeue56, who has done a great deal of code-gen in Elm)
|
This came up in the string interpolation discussion, as I'm curious - is anyone depending on the current behavior, and couldn't work around such a change with |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rtfeldman
Jul 4, 2016
Member
To be more specific on that last point, in a world where toString on a String worked the same way as the identity function, I'd expect toString >> Json.Encode.string >> Json.Encode.encode 0 to work exactly like toString does today.
I expect this based on how in JavaScript, JSON.stringify("foo") returns a string that is five characters long: foo with quotes around it.
|
To be more specific on that last point, in a world where I expect this based on how in JavaScript, |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
avh4
Jul 5, 2016
Member
toString currently has a specific purpose: to give a representation of a thing that matches what you would type in Elm source code to get that thing. If you have a string already and want to display that string as it is, just display the string.. don't call toString on it.
If you are toStringing a record or a union type, it's because you are displaying it for debugging purposes. If you are toStringing a float, you really should be using some kind of number formatting. toStringing an int is currently the only reasonable case where you would use toString in production code, and this could be fixed by introducing String.fromInt.
The behavior of toString in other languages was mentioned, but I don't think those are good examples to follow. Especially in statically typed languages, it is generally not advised to use toString (for example). The current behavior of toString is consistent and clearly-defined and I don't think we want to introduce a change that will give Elm's toString all of the ambiguities that Java, Javascript, etc's toStrings have.
|
If you are The behavior of |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rtfeldman
Jul 5, 2016
Member
I hadn't considered the possibility that interpolation might not actually desugar to a toString call in the case of strings. Fair enough! I guess that discussion can be decoupled from this one.
|
I hadn't considered the possibility that interpolation might not actually desugar to a |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
kirked
Jul 5, 2016
@avh4 Thanks for the explanation as to the purpose of toString, it's not in the docs. Does it then have any use to an app programmer? (Should it be in the public API if it's useless?)
I don't buy your assertion that ...in statically typed languages, it is generally not advised to use toString. I've worked in statically typed languages for > 20 years, and have found it quite common to call toString to get a display value.
@rtfeldman, Thanks for pointing out the discussion about interpolation. If/when that is available (I wish it was today!), I would choose that way of representing the value in the view.
FWIW, I was lurking on the Slack list a bit last evening, and this very same issue came up from another person on the list (I didn't comment, but had a little chuckle). I think you're definitely working against the Principle of Least Surprise here.
kirked
commented
Jul 5, 2016
|
@avh4 Thanks for the explanation as to the purpose of I don't buy your assertion that ...in statically typed languages, it is generally not advised to use @rtfeldman, Thanks for pointing out the discussion about interpolation. If/when that is available (I wish it was today!), I would choose that way of representing the value in the view. FWIW, I was lurking on the Slack list a bit last evening, and this very same issue came up from another person on the list (I didn't comment, but had a little chuckle). I think you're definitely working against the Principle of Least Surprise here. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
JoshCheek
Aug 15, 2016
Looked in the Mailing List and didn't see an issue for this, read through the most promising one about toString but it was really about namespacing, so I'll post here despite the bot's suggestion that I don't:
Due to historical context, the name would lead everyone coming to Elm to assume it returns a String representation of the argument, for purposes like interpolation, where toString on a String should be identity. Now, I suspect that @avh4 is right in https://github.com/elm-lang/core/issues/657#issuecomment-230389564, but even if he is, the name is setting incorrect expectations, and there's no path from that expectation to whatever the better way is. So, regardless of opinions about whether a toString function as I described should exist, it seems clear to me that the existing one should be renamed.
What do other languages call it? Given that Haskell calls it show (docs)? Ruby calls it inspect (inspect, to_s), JavaScript calls it inspect and dir (inspect, dir, toString), Python has calls the module for this sort of thing inspect, and returns a list of functions from dir (inspect, dir).
What should Elm call it? For the reasons above, I'd advocate inspect or show, and I'd prefer inspect as show implies it should be readable, but that's never the context I use such a method in, and it would limit me from displaying useful information in the output. It's also worth considering a context outside the browser, like the shell (I assume Elm is headed in that direction).
JoshCheek
commented
Aug 15, 2016
|
Looked in the Mailing List and didn't see an issue for this, read through the most promising one about Due to historical context, the name would lead everyone coming to Elm to assume it returns a String representation of the argument, for purposes like interpolation, where What do other languages call it? Given that Haskell calls it What should Elm call it? For the reasons above, I'd advocate |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
OvermindDL1
Aug 15, 2016
Another vote for inspect.
However, an alternative is the ability to make functions of different types have the same name, that way something like this would be valid if-and-only-if the call path is resolvable from the point it is called at, if the function call is ambiguous (like not having enough arguments to fully determine which should be called) then the compiler should throw an error. This is how many statically typed functional languages work and would work around this issue. Another method would be a function matcher style, where you can have multiple heads of a function and they match on their values and value-types (only if resolvable at compile-time else compiler throws an error), which effectively gives the same ability as the above but is often easier to implement in the compiler while also being more powerful.
OvermindDL1
commented
Aug 15, 2016
|
Another vote for inspect. However, an alternative is the ability to make functions of different types have the same name, that way something like this would be valid if-and-only-if the call path is resolvable from the point it is called at, if the function call is ambiguous (like not having enough arguments to fully determine which should be called) then the compiler should throw an error. This is how many statically typed functional languages work and would work around this issue. Another method would be a function matcher style, where you can have multiple heads of a function and they match on their values and value-types (only if resolvable at compile-time else compiler throws an error), which effectively gives the same ability as the above but is often easier to implement in the compiler while also being more powerful. |
kirked commentedJul 4, 2016
•
edited
Edited 1 time
-
kirked
edited Jul 4, 2016 (most recent)
In most popular languages (Java, Javascript, Clojure, Scala to name a few),
toStringsimply provides a string representation of a value. However, in Elm it seems to provide a syntax writer (I'm thinking the dual of something like the Clojure reader).There's one edge case where that easily bites: when the value is a
Stringalready, toString wraps it in quotes:Writing generalised code as I do, I wrote a helper to extract a value from Maybe:
To my surprise, my displayed text was quoted. It seems there's no way in Elm to properly express the desired function above, since you can't tell at runtime if a value is a String.
After a short discussion on Slack #general 4 Jul 2016 1:12am CDT, I posited:
I propose moving or renaming the current toString and providing an implementation that behaves as one would expect coming from other popular languages. Or just give me the ability to tell if a value is a string at runtime, and I can work around this edge case.
Thoughts?