{"id":17892411,"url":"https://github.com/toastal/return-optics","last_synced_at":"2025-03-23T00:32:34.682Z","repository":{"id":62419612,"uuid":"71526425","full_name":"toastal/return-optics","owner":"toastal","description":"Extending Return with Lenses to do fun things in the Elm update function","archived":false,"fork":false,"pushed_at":"2017-10-28T22:39:44.000Z","size":12,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T15:54:42.994Z","etag":null,"topics":["elm","optics","return"],"latest_commit_sha":null,"homepage":"http://package.elm-lang.org/packages/toastal/return-optics/latest","language":"Elm","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toastal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-21T03:29:51.000Z","updated_at":"2019-01-03T09:29:25.000Z","dependencies_parsed_at":"2022-11-01T17:03:22.677Z","dependency_job_id":null,"html_url":"https://github.com/toastal/return-optics","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toastal%2Freturn-optics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toastal%2Freturn-optics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toastal%2Freturn-optics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toastal%2Freturn-optics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toastal","download_url":"https://codeload.github.com/toastal/return-optics/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245040235,"owners_count":20551297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elm","optics","return"],"created_at":"2024-10-28T14:36:14.286Z","updated_at":"2025-03-23T00:32:34.427Z","avatar_url":"https://github.com/toastal.png","language":"Elm","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Return.Optics\n\n`Return.Optics` is a utility library extending `Return` with `Monocle` making a clean, concise \u003cabbr title=\"application programming interface\"\u003eAPI\u003c/abbr\u003e for doing Elm component updates in the context of other updates. Initially it includes helper functions around refraction—the bending of light. Like viewing a straw being inserted into a glass of water, we’ll use a `Lens` to bend our top-level update function into our component update, and when we pull it out, well be left with an unbent `( model, Cmd msg )` of the Elm architecture.\n\nIf you would like a more in-depth read into why, you can read about that on [my blog](https://toast.al/posts/2016-10-20-optical-swordplay-with-components.html).\n\nHowever, if that’s not your thing and doesn’t make sense, you’re in luck because we’re about to go over an example.\n\nSuppose we have this trivial, toy component and model…\n\n\n#### Models\n\n```elm\nmodule Model exposing (Model)\n\nimport Checkbox.Model as Checkbox\n\n\ntype alias Model =\n    { pageTitle : String\n    , checkbox : Checkbox.Model\n    }\n```\n\n```elm\nmodule Checkbox.Model exposing (Model)\n\ntype alias Model =\n    { checked : Bool\n    }\n```\n\n\n#### Msgs\n\n```elm\nmodule Msg exposing (Msg(..))\n\nimport Checkbox.Msg as Checkbox\n\n\ntype Msg\n    = TitleChange String\n    | CheckboxMsg Checkbox.Msg\n```\n\n```elm\nmodule Checkbox.Msg exposing (Msg(..))\n\ntype Checkbox\n    = CheckMe Bool\n```\n\n\nAssuming we have built up some `cmdWeAlwaysDo`, with the standard library we’d write updates like this:\n\n\n#### Stardard Updates\n\n```elm\nmodule Update exposing (update)\n\nimport Checkbox.Update as Checkbox\nimport Model\nimport Msg exposing (Msg(TitleChange, CheckboxMsg))\n\n\nupdate : Msg -\u003e Model -\u003e ( Model, Cmd Msg )\nupdate msg model =\n    let\n        cmdWeAlwaysDo : Cmd Msg\n        cmdWeAlwaysDo =\n            -- insert a real command in a non-toy app\n            Cmd.none\n    in\n        case msg of\n            TitleChange title -\u003e\n                ( { model | pageTitle = title }, cmdWeAlwaysDo )\n\n            CheckboxMsg cbMsg -\u003e\n                let\n                    ( cbModel, cbCmd )\n                        Checkbox.Update cbMsg model.checkbox\n                in\n                    { model | checkbox = cbModel }\n                        ! [ cbCmd\n                          , cmdWeAlwaysDo\n                          ]\n```\n\n```elm\nmodule Checkbox.Update exposing (update)\n\nimport Checkbox.Model as Model\nimport Checkbox.Msg as Msg exposing (Msg(CheckMe))\n\n\nupdate : Msg -\u003e Model -\u003e ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        CheckMe bool -\u003e\n            { model | checked = bool }\n```\n\n\n- - -\n\n\nUsing `Return.Optics.refractl` and `Lens`es we can instead change our model files and our update files like this:\n\n```elm\nmodule Model exposing (..)\n\nimport Monocle.Lens exposing (Lens)\nimport Checkbox.Model as Checkbox\n\n\ntype alias Model =\n    { pageTitle : String\n    , checkbox : Checkbox.Model\n    }\n\n\npageTitlel : Lens Model String\npageTitlel =\n    Lens .pageTitle (\\p m -\u003e { m | pageTitle = p })\n\n\ncheckboxl : Lens Model Checkbox.Model\ncheckboxl =\n    Lens .checkbox (\\c m -\u003e { m | checkbox = c })\n```\n\n```elm\nmodule Checkbox.Model exposing (..)\n\nimport Monocle.Lens exposing (Lens)\n\n\ntype alias Model =\n    { checked : Bool\n    }\n\n\ncheckedl : Lens Model Bool\ncheckedl =\n    Lens .checked (\\c m -\u003e { m | checked = c })\n```\n\n```elm\nmodule Update exposing (update)\n\nimport Return exposing (Return)\nimport Return.Optics exposing (refractl)\nimport Checkbox.Update as Checkbox\nimport Model\nimport Msg exposing (Msg(TitleChange, CheckboxMsg))\n\n\nupdate : Msg -\u003e Model -\u003e Return Msg Cmd\nupdate msg =\n    let\n        cmdWeAlwaysDo : Cmd Msg\n        cmdWeAlwaysDo =\n            -- insert a real command in a non-toy app\n            Cmd.none\n    in\n        Return.singleton\n            \u003e\u003e Return.command cmdWeAlwaysDo\n            \u003e\u003e case msg of\n                TitleChange title -\u003e\n                    Return.map (.set Model.pageTitlel title)\n\n                -- Note how much more condensed this part is\n                CheckboxMsg cbMsg -\u003e\n                    refractl Model.checkboxl CheckboxMsg (Checkbox.update cbMsg)\n```\n\n```elm\nmodule Checkbox.Update exposing (update)\n\nimport Checkbox.Model as Model\nimport Checkbox.Msg as Msg exposing (Msg(..))\n\n\nupdate : Msg -\u003e Model -\u003e Return Msg Model\nupdate msg =\n    Return.singleton\n        \u003e\u003e case msg of\n            CheckMe bool -\u003e\n                Return.map (.set Model.checkedl bool)\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoastal%2Freturn-optics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoastal%2Freturn-optics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoastal%2Freturn-optics/lists"}