-
Notifications
You must be signed in to change notification settings - Fork 30
Open
Description
Suppose I have a map like this:
type Employee =
{
JobTitle : string
Salary : int
}
with
static member Salary_ =
(fun x -> x.Salary), (fun v x -> { x with Salary = v })
let employees =
Map.empty
|> Map.add "alice" { JobTitle = "Manager"; Salary = 86 }
|> Map.add "bob" { JobTitle = "Customer Support"; Salary = 76 }
I want to create an optic for updating the salaries. Something like:
let myLens name =
Map.value_ name >-> Employee.Salary_
However, this optic is Lens<Map<string, Employee>, int option>.
Instead, I would like a Lens<Map<string, Employee>, int>, by providing a default int value.
Something like:
// Not real code
let myLens name =
Map.value_ name >-> Employee.Salary_ >-> Lens.defaultValue 0
How should I do this?
Here is what I came up with, but I have a feeling this is already built into the library:
let composeOption (b : Lens<'b, 'c>) (a : Lens<'a, 'b option>) : Lens<'a, 'c option> =
let getA, setA = a
let getB, setB = b
let get = (fun x -> getA x |> Option.map getB)
let set = (fun (v : 'c option) (x : 'a) ->
match getA x with
| Some b ->
match v with
| Some c -> x |> setA (setB c b |> Some)
| None -> x
| None -> x
)
get, setMetadata
Metadata
Assignees
Labels
No labels