NoRedInk / elm-saved / Saved

A type to keep track of a value that can be saved. It keeps track of the changes to a value since it was last saved.

Internally the Saved a keeps track of two values: the last saved value and the current value.


type Saved a

A type representing a value that can be saved.

new : a -> Saved a

Take a value and wrap it into a Saved a. This initial value is marked as having been saved.

new "Bear"
    |> saved --> True

value : Saved a -> a

Get the current value from a Saved a.

new "Bear"
    |> value --> "Bear"

change : (a -> a) -> Saved a -> Saved a

Modify the current value in your Saved a using a function. This does not affect the last saved value.

new "Bear"
    |> change (\animal -> animal ++ "s")
    |> saved
    --> False

save : Saved a -> Saved a

Save the current value.

new "Bear"
    |> change (\animal -> animal ++ "s")
    |> save
    |> saved
    --> True

discard : Saved a -> Saved a

Discard any changes and reset the current value to the last saved value.

new "Bear"
    |> change (\animal -> animal ++ "s")
    |> discard
    |> value
    --> "Bear"

saved : Saved a -> Basics.Bool

Check if any changes have been made since the value was last changed.

new "Bear"
    |> saved
    --> True

new "Bear"
    |> change (\animal -> animal ++ "s")
    |> saved
    --> False

Advanced

These functions can be very useful. They are not the best way to get to know this library though, which is why they are split out into this section.

setSaved : a -> Saved a -> Saved a

Set the last saved value, keeping the current value unchanged.

You might use this when your backend reports to you a previous value was saved, but your user might have made new changes in the meanwhile.

If you want to immediately mark the current value as saved you can use save.

new "Bear"
    |> change (\animal -> animal ++ "s")
    |> change (\animal -> animal ++ "kin")
    |> setSaved "bears"
    |> saved
    --> False

update : (a -> ( a, cmd )) -> Saved a -> ( Saved a, cmd )

This function is like change, but allows your changing function to produce a command. This is typically useful in the update function of your program.

map : (a -> b) -> Saved a -> Saved b

Map over the values in a saved.

Beware that this applies the mapping function to both the last saved and the current value, and so should not be used to make changes only to the current value (for that, use 'change').

As a rule of thumb, if your map function does not go from a type to another type and so is a -> a, you probably don't want to use this.

Using a custom equality check

To determine whether a Saved a has changes, the saved and changed values are compared. Sometimes you may want to use a custom equality check for this. The functions below allow you to create Saved a instances with such a custom check.


type alias Eq a =
a -> a -> Basics.Bool

Alias for an equality function used to tell if two values are equal. For most purposes this can be ==, but some types require a customized equality check.

customNew : Eq a -> a -> Saved a

Like new, but allowing you to specify an equality function.

customMap : Eq b -> (a -> b) -> Saved a -> Saved b

Like map, but allowing you to specify a new equality function for the new type returned from the mapping function.