Reputation: 4219
I have a type
type alias WithStatus l =
{ l
| status :
Status
}
This extends a record with a status field.
Now I'd like to make a function that takes a record and gives it a particular status, so I made:
addStatus : Status -> l -> WithStatus l
addStatus status l =
{ l
| status =
status
}
However elm complains that l
could potentially not be a record.
This is not a record, so it has no fields to update!
21|> { l
22| | status =
23| status
24| }
This `l` value is a:
l
But I need a record!
Which is true. However elm has no way of knowing that the l
in the type alias is a record either, it checks for that on the use site. So it seems a little odd that it's complaining here.
Is there a way to express a function which takes any record l
and adds a status?
Upvotes: 1
Views: 142
Reputation: 29126
Is there a way to express a function which takes any record l and adds a status?
You can do
setStatus : Status -> WithStatus l -> WithStatus l
setStatus status l =
{ l | status = status }
which replaces an existing status, but the ability to introduce new fields in the way you were hoping isn't possible any more.
It used to be, from 0.7 until 0.16 (released in 2015) where it was removed because it wasn't felt to be actually all that useful:
Simplified Records
There is kind of a long story here. The short version is that record update uses a normal equals sign now, like this:
{ point | x = 4 }
Instead of using the backwards arrow <- like before. This was something that a lot of people got tripped up on, even after they had a lot of experience, so overall I think this will make things a bit friendlier. The backwards arrows also led to weird code texture when used within a case such that you have forwards and backwards arrows going everywhere.
Okay, but the long story is interesting if you are into language design!
Elm uses a very cool record system. It is based on an excellent paper by Daan Leijen that lets you add and remove fields from records, all while keeping the types simple. I really love this mix of power and simplicity!
I added support for this back in 0.7, and at the time, I had never seen a language (with a real working compiler) that allowed field addition and deletion like this. So I had intuition, but no way to get real experience. I worried that it could encourage overly complex code, so from the start I was very conservative, knowing that we could expand or contract the features as we got more data.
Well it has been more than two years since then, and the results are in. Pretty much no one ever used field addition or deletion. In the few cases where people did use it, it got pretty crazy pretty quickly. The one real-world case I know of is recorded here if you want to see, and the code could be rewritten with custom types, which turned out nicer anyway.
Removing addition and deletion will also make Elm easier to optimize (described more here). This is especially true if we are targeting platforms besides JavaScript, but allows some simplifications in JS too. In fact, the benchmarks we ran for 0.16 show that this made record updates a lot faster!
Upvotes: 4