Elm currently has this feature:
type alias B a = { a | b1 : String, b2 : Bool }
and then lets one write B A
for “the record type A
plus the B
-fields”.
But actually using that feature is problematic: https://groups.google.com/d/msg/elm-discuss/AaL8iLjhEdU/JSAXV2oACgAJ
Its availability leads people to want to do things that are not supported and not intended: https://github.com/elm-lang/elm-compiler/issues/1283
Evan has said he knows no examples where using that feature in the above way (creating B A
from A
) is the best way to model something: https://groups.google.com/d/msg/elm-discuss/AaL8iLjhEdU/pBe29vQdCgAJJ
And yet the feature is in the language, so tempts people into “wrong modelling” etc.
(See also https://github.com/elm-lang/elm-compiler/issues/1308.)
What about weakening the feature in the following way to address these issues but keep uses that are actually intended?
My proposal is to not anymore have syntax { a | b1 : String, b2 : Bool }
for “the record type that is a
extended with b1
and b2
fields”, but instead have the syntax { _ | b1 : String, b2 : Bool }
for “some record type containing b1
and b2
fields”.
I’m seeking answers to the following question:
Does anybody have an example that can be written in Elm 0.16 and that represents a “good” (sanctioned/intended) use of extensible records that could not anymore be written after this proposal is implemented?
As a first sanity check, note that intended/motivated uses like the one present in the docs page would still be supported:
origin =
{ x = 0
, y = 0
}
lady =
{ name = "Lois Lane"
, age = 31
}
dude =
{ x = 0
, y = 0
, name = "Clark Kent"
, velocity = 42
, angle = degrees 30
}
type alias Named =
{ _ | name : String }
getName : Named -> String
getName { name } =
name
names : List String
names =
[ getName dude, getName lady ]
type alias Positioned =
{ _ | x : Float, y : Float }
getPos : Positioned -> (Float,Float)
getPos { x, y } =
(x,y)
positions : List (Float,Float)
positions =
[ getPos origin, getPos dude ]
--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/CAGkFuyDBW33ty_xUi9wW4dXm_f_thekj7WitP1T3sJFjM5ajxA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
I assume you meant
join : List Widget -> Html
join xs = div [] (List.map .repr xs)
(not join : List Widget
).
The answer to your question is that no, it would not be possible to apply join
to a mixed list containing Button
s and Label
s. It follows directly from the fact that the type would desugar to
join : List { _ | size : (Int, Int), pos : (Int, Int), repr : Html } -> Html
There’s no intent (and no potential in the implementation of all this that I envisage) for interpreting the _
in two different ways in two different list elements.
More generally, note that the question I asked was:
Does anybody have an example that can be written in Elm 0.16 and that represents a “good” (sanctioned/intended) use of extensible records that could not anymore be written after this proposal is implemented?
I didn’t ask the converse question whether there are examples that cannot be written in Elm 0.16 but could be written after my proposal is implemented. I did not ask this converse question because I know the answer to that question. It is: No.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/CACpbLo%2BBELSJi-RKQX9eC6OScHb6k7yMtF0U-zxmjqo5GR70YA%40mail.gmail.com.
Motivated by Peter’s question, let me amend my proposal.
In addition to:
My proposal is to not anymore have syntax
{ a | b1 : String, b2 : Bool }
for “the record type that isa
extended withb1
andb2
fields”, but instead have the syntax{ _ | b1 : String, b2 : Bool }
for “some record type containingb1
andb2
fields”.
there is now also:
_
can occur in a type
or type alias
declaration.How the example from the docs page then looks like is given further below.
Let me reiterate that I am not trying to make more examples valid than are currently valid. I am trying to weaken, not strengthen, what one can do with record types. Because what one can currently do with them tempts people into a direction that is undesired (from a conceptual/modelling perspective) and that, if they follow it nevertheless, sometimes leads them into a dead end eventually.
The question still is whether I am weakining the feature too much:
Does anybody have an example that can be written in Elm 0.16 and that represents a “good” (sanctioned/intended) use of extensible records that could not anymore be written after this proposal is implemented?
origin =
{ x = 0
, y = 0
}
lady =
{ name = "Lois Lane"
, age = 31
}
dude =
{ x = 0
, y = 0
, name = "Clark Kent"
, velocity = 42
, angle = degrees 30
}
getName : { _ | name : String } -> String
getName { name } =
name
names : List String
names =
[ getName dude, getName lady ]
getPos : { _ | x : Float, y : Float } -> (Float,Float)
type alias PlayerViewModel a =
{ a
| playStatus : PlayStatus
, currentTimeAtPlayStart : Time.Time
}
You could model your situation as follows:
type alias PlayerViewModel a =
{ base : a
, playStatus : PlayStatus
, currentTimeAtPlayStart : Time.Time
}
That would give you all the advantages (abstraction, aliasing, short signatures) that you describe you have with your current modelling, right?
Evan has stated that he hasn’t seen any example where record nesting is not better than record extension.
If your example is a counter-example to my proposal, it is also a counter-example of the kind that Evan asked for in that other thread (with consequences for the dicussion topic over there). In other words, the current conclusion of that other thread seems to imply that your example is actually a not-desirable use case. Which in turn would imply that my proposal making it invalid would be a good thing, not a bad thing.
--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/5f8a6287-9a0e-4d0b-b9fe-5434bd270fb1%40googlegroups.com.
Yet another alternative (maybe better than the one from my previous message) that would also be compatible with my proposal would be:
Don’t have the PlayerViewModel
alias.
Have:
type alias Playing =
{ playStatus : PlayStatus
, currentTimeAtPlayStart : Time.Time
}
Let the models of the Slideshow Editor and Viewer contain a field playing : Playing
instead of two fields playStatus : PlayStatus
and currentTimeAtPlayStart : Time.Time
.
Where previously you had a signature like
fun : PlayerViewModel a -> ...
now have a signature like
fun : { _ | playing : Playing } -> ...
What would be downsides of this approach compared to your current one? Do you have signatures in your project that couldn’t be handled nicely that way?
{ model.playing
| playStatus = Stopped --assuming PlayStatus to be a simple Union of Stopped | Playing
}
{ model.playing.playStatus
| isPlaying = False --assuming PlayStatus to have a Bool field isPlaying
}
planarDistance : { a | x : Float, y : Float} -> { a | x : Float, y : Float} -> Float
Wouldn't there be cases where you want to specify that the extended type is the same, especially for the return value? Like, if you have a function that sets the x coordinate to 0, you want a guarantee that it doesn't change the number of fields. But it's also something you'd want to work for 2d and 3d vectors polymorphically.
--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/c3fa239d-96cc-4c0f-9ce3-c348d6b63573%40googlegroups.com.
Joey’s example convinces me that my proposal is not viable.
We want to be able to give a meaningful type to this function:
setXtoZero rec = { rec | x = 0.0 }
(Incidentally, the type Elm currently infers for this function is not the one it should be according to the specification of “there’s no record field extension or deletion in the expression syntax”.)
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/CADT%2BLxqW_w83_6otO3%2BqESMgcW%3Dz%2BEe%2Bv%2BrWR6N3VYxQ0_8rrw%40mail.gmail.com.
> setXtoZero rec = { rec | x = 0.0 }
<function> : { b | x : a } -> { b | x : Float }
> setXtoZero { x = "huh?" }
{ x = 0 } : { x : Float }
The compiler correctly constrains the unspecified fields to be the same type, b. (So now I see where that is desirable; contrast my previous post.) However it should restrict the type of x. Janis should open an issue.
--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/3c91cd86-b2cf-44c1-b2a9-eec8b6256146%40googlegroups.com.