Skip to content

Instantly share code, notes, and snippets.

@JoeyEremondi
Last active August 15, 2016 15:02
Show Gist options
  • Save JoeyEremondi/b5b1be78d7c59aedf2347996d473702d to your computer and use it in GitHub Desktop.
Save JoeyEremondi/b5b1be78d7c59aedf2347996d473702d to your computer and use it in GitHub Desktop.
-- Given these simplified types:
data Model = Model { something :: SomeSubData }
data SomeSubData = SomeSubData { moreThing :: Integer }
-- And given this value
where
model = Model (SomeSubData 42)
-- You could do the way that Elm does now (although elm has the existing record inside the {} and haskell has it outside, so this is how haskell does it):
newModel = model {
something = (something model) {
moreThing = moreThing (something model) + 1
}
}
-- The above set newModel as { something = { moreThing = 43 } } in Elmish parlance, and is very similar to how it is done in Elm itself, however Haskell has HKT's, which allow for a variety of other methods such as:
-- references+lenses (not possible to do anything even remotely like this in Elm right now due to not being able to operate over types, but it is the most succinct):
$(mkLabels [ 'Model, 'SomeSubData ]) -- Only need to do this once
newModel = modify (+1) (moreThing . something) model
-- SYB (A generic library that handles tasks like this with is, it comes bundled with Haskell
incMoreThing v s@(SomeSubData moreThing) = s { moreThing = moreThing + v } -- Per change you want to make anywhere in the record path
newModel = everywhere (mkT (incMoreThing 1))
-- Semantic Editor Combinators (low-level version of SYB, no libraries needed, and you could make these 'now' in Elm, and I have to an extent, but it is very easy in haskell to define it from scratch, as doing here, still very wordy as it requires one function made per key):
type SemEdit a = a -> a
type Lifter p q = SemEdit p -> SemEdit q
onSomething :: Lifter SomeSubData Model
onSomething f (Model something) = Model (f something)
onMoreThing :: Lifter Integer SomeSubData
onMoreThing f (SomeSubData moreThing) = SomeSubData
newModel = (onSomething . onMoreThing) (+1) model
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment