- Notifications
You must be signed in to change notification settings - Fork2
Extending Return with Lenses to do fun things in the Elm update function
License
toastal/return-optics
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Return.Optics
is a utility library extendingReturn
withMonocle
making a clean, concise API 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 aLens
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.
If you would like a more in-depth read into why, you can read about that onmy blog.
However, if that’s not your thing and doesn’t make sense, you’re in luck because we’re about to go over an example.
Suppose we have this trivial, toy component and model…
moduleModelexposing (Model)importCheckbox.ModelasCheckboxtype aliasModel={ pageTitle:String, checkbox:Checkbox.Model}
moduleCheckbox.Modelexposing (Model)type aliasModel={ checked:Bool}
moduleMsgexposing (Msg(..))importCheckbox.MsgasCheckboxtypeMsg=TitleChangeString|CheckboxMsgCheckbox.Msg
moduleCheckbox.Msgexposing (Msg(..))typeCheckbox=CheckMeBool
Assuming we have built up somecmdWeAlwaysDo
, with the standard library we’d write updates like this:
moduleUpdateexposing (update)importCheckbox.UpdateasCheckboximportModelimportMsgexposing (Msg(TitleChange, CheckboxMsg))update:Msg->Model-> (Model,CmdMsg )updatemsg model=let cmdWeAlwaysDo:CmdMsg cmdWeAlwaysDo=-- insert a real command in a non-toy appCmd.noneincasemsgofTitleChange title->({ model| pageTitle= title}, cmdWeAlwaysDo)CheckboxMsg cbMsg->let( cbModel, cbCmd)Checkbox.Update cbMsg model.checkboxin{ model| checkbox= cbModel}![ cbCmd, cmdWeAlwaysDo]
moduleCheckbox.Updateexposing (update)importCheckbox.ModelasModelimportCheckbox.MsgasMsgexposing (Msg(CheckMe))update:Msg->Model-> (Model,CmdMsg )updatemsg model=casemsgofCheckMe bool->{ model| checked= bool}
UsingReturn.Optics.refractl
andLens
es we can instead change our model files and our update files like this:
moduleModelexposing (..)importMonocle.Lensexposing (Lens)importCheckbox.ModelasCheckboxtype aliasModel={ pageTitle:String, checkbox:Checkbox.Model}pageTitlel:LensModelStringpageTitlel=Lens.pageTitle(\p m->{ m| pageTitle= p})checkboxl:LensModelCheckbox.Modelcheckboxl=Lens.checkbox(\c m->{ m| checkbox= c})
moduleCheckbox.Modelexposing (..)importMonocle.Lensexposing (Lens)type aliasModel={ checked:Bool}checkedl:LensModelBoolcheckedl=Lens.checked(\c m->{ m| checked= c})
moduleUpdateexposing (update)importReturnexposing (Return)importReturn.Opticsexposing (refractl)importCheckbox.UpdateasCheckboximportModelimportMsgexposing (Msg(TitleChange, CheckboxMsg))update:Msg->Model->ReturnMsgCmdupdatemsg=let cmdWeAlwaysDo:CmdMsg cmdWeAlwaysDo=-- insert a real command in a non-toy appCmd.noneinReturn.singleton>>Return.command cmdWeAlwaysDo>>casemsgofTitleChange title->Return.map(.setModel.pageTitlel title)-- Note how much more condensed this part isCheckboxMsg cbMsg-> refractlModel.checkboxlCheckboxMsg(Checkbox.update cbMsg)
moduleCheckbox.Updateexposing (update)importCheckbox.ModelasModelimportCheckbox.MsgasMsgexposing (Msg(..))update:Msg->Model->ReturnMsgModelupdatemsg=Return.singleton>>casemsgofCheckMe bool->Return.map(.setModel.checkedl bool)
About
Extending Return with Lenses to do fun things in the Elm update function