{"action":"created","issue":{"url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/984","labels_url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/984/labels{/name}","comments_url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/984/comments","events_url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/984/events","html_url":"https://github.com/elm-lang/elm-compiler/issues/984","id":94133675,"number":984,"title":"Proposal: Field update/map syntax","user":{"login":"TheSeamau5","id":3227869,"avatar_url":"https://avatars.githubusercontent.com/u/3227869?v=3","gravatar_id":"","url":"https://api.github.com/users/TheSeamau5","html_url":"https://github.com/TheSeamau5","followers_url":"https://api.github.com/users/TheSeamau5/followers","following_url":"https://api.github.com/users/TheSeamau5/following{/other_user}","gists_url":"https://api.github.com/users/TheSeamau5/gists{/gist_id}","starred_url":"https://api.github.com/users/TheSeamau5/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheSeamau5/subscriptions","organizations_url":"https://api.github.com/users/TheSeamau5/orgs","repos_url":"https://api.github.com/users/TheSeamau5/repos","events_url":"https://api.github.com/users/TheSeamau5/events{/privacy}","received_events_url":"https://api.github.com/users/TheSeamau5/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":25,"created_at":"2015-07-09T19:31:20Z","updated_at":"2015-07-10T04:42:08Z","closed_at":null,"body":"Suppose you have the record:\r\n\r\n```elm\r\np = { x = 1 , y = 2 }\r\n```\r\n\r\nYou can access a field from the record in one of two ways\r\n\r\n```elm\r\n-- 1) direct dot syntax on the variable\r\np.x \r\n\r\n-- 2) as a getter function\r\n.x p\r\n\r\n-- The getter function is particularly useful as a function\r\n-- that can be passed to other functions (such as `List.map`)\r\n```\r\n\r\nBut, on the other hand, you can \"set\" a field in a record in one way\r\n\r\n```elm\r\n{ p | x <- someValue }\r\n```\r\n\r\nwhich can get pretty verbose when wanting to pass this updating as a function\r\n\r\n```elm\r\nsetX someValue p = { p | x <- someValue }\r\n```\r\n\r\nThe idea of this proposal is very simple, to have a shorthand syntax for setters that is analogous to the function form of getters.\r\n\r\nFor example, setting the field x could be done via the `!x` function where\r\n\r\n```elm\r\n!x :  (a -> b) -> { r | x : a } -> { r | x : b }\r\n```\r\n\r\nThis function would take a mapping which would be applied to the value of the \"x\" field. \r\n\r\nAs with the getters, this syntax would be present in the language and thus can be used for fields of any names.\r\n\r\n```elm\r\n!x (always 5) p == { x = 5, y = 2 }\r\n\r\n!x ((+) 1) p == { x = 1, y = 2 }\r\n```\r\n\r\nFurthermore, nested updates are trivial\r\n\r\nSuppose you have the following type\r\n\r\n```elm\r\ntype alias Entity = \r\n  { position : { x : Float , y : Float } }\r\n```\r\n\r\nand you have a value of type Entity called `entity`\r\n\r\n```elm\r\nentity : Entity\r\nentity = \r\n  { position = { x = 0, y = 1 } }\r\n```\r\n\r\nand you wish to increment only the x value. You do it via function composition\r\n\r\n```elm\r\n(!x >> !position) ((+1)) entity == { position = { x = 1, y = 1 } }\r\n```\r\n\r\nUnder this proposal, function composition suffices to update values as deeply nested as you want. One only needs to remember that the composition starts from the inner-most field you wish to update.\r\n"},"comment":{"url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/comments/120223014","html_url":"https://github.com/elm-lang/elm-compiler/issues/984#issuecomment-120223014","issue_url":"https://api.github.com/repos/elm-lang/elm-compiler/issues/984","id":120223014,"user":{"login":"Apanatshka","id":1237863,"avatar_url":"https://avatars.githubusercontent.com/u/1237863?v=3","gravatar_id":"","url":"https://api.github.com/users/Apanatshka","html_url":"https://github.com/Apanatshka","followers_url":"https://api.github.com/users/Apanatshka/followers","following_url":"https://api.github.com/users/Apanatshka/following{/other_user}","gists_url":"https://api.github.com/users/Apanatshka/gists{/gist_id}","starred_url":"https://api.github.com/users/Apanatshka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Apanatshka/subscriptions","organizations_url":"https://api.github.com/users/Apanatshka/orgs","repos_url":"https://api.github.com/users/Apanatshka/repos","events_url":"https://api.github.com/users/Apanatshka/events{/privacy}","received_events_url":"https://api.github.com/users/Apanatshka/received_events","type":"User","site_admin":false},"created_at":"2015-07-10T04:42:08Z","updated_at":"2015-07-10T04:42:08Z","body":":+1: for the `@` prefix. If you provide a record using the `@` syntax, you could simply add the `add` and `remove` to that record too, and make extendable `Focus big small recordExtension`. Composing would then be: `(=>) : Focus big medium r1 -> Focus medium small r2 -> Focus big small {}`"}}