question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using setl and view for the same optic in one function gives error "The type Data.Identity does not match the type Data.Const"

See original GitHub issue

I’m trying to use optics to set a record field together with the record’s UpdatedAt: DateTimeOffset field only if the field value has changed.

I have created the following generic function, which doesn’t compile:

let inline private setField valueOptic value updatedAtOptic now source =
  let oldVal = view valueOptic source
  if value = oldVal then source
  else
    setl valueOptic value source
    |> setl updatedAtOptic now

image

What am I doing wrong?

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:23 (21 by maintainers)

github_iconTop GitHub Comments

3reactions
gustycommented, Aug 30, 2020

That was a tip for @wallymathieu / @gusty for a change in FSharpPlus, right? Not in user code?

We can consider using those functors for lensing but of course, we’ll need to make sure all other optics don’t break. Testing should be added although there is some lens coverage already, but we’ll need to add test for stuff that was previously not allowed, like your use case. Feel free to open PR or a draft PR to play with it.

Would be great it FSharpPlus could solve this natively,

We can’t fix type system limitations (like rank-n types) but we can certainly explore tricks like the suggested one that makes a better user experience.

or illuminate whether lenses is the wrong tool for this kind of job

TBH I’m not an expert in lenses, it is an abstraction that it’s not specific to this library or to F# so I would try to find guidance in other places as well, for instance I asked your question in the FP slack, in the #Lens channel as I’m also curious to see if/how lens would help in that situation.

My feeling is that we need a lens that encapsulate that behavior, we can certainly create it like this:

let inline _nameWithUpdate now f p =
    map (fun v -> if v = p.Name then { p with Name = v } else { p with Name = v; UpdatedAt = now; NameHistory = p.Name::p.NameHistory }) (f p.Name)

but I understand that you want to derive it in a general way, and I think that would involve using other functors in anycase. So if you’re happy with the mutable solution stick to it. I personally like it because yes it does a mutation but it’s encapsulated inside the function, it doesn’t leak outside, as opposed to the solution of passing twice the lens.

2reactions
gustycommented, Aug 31, 2020

A similar technical problem was reported by @reinux on our gitter 2 weeks ago:

Hey, hopefully quick question: is there a type alias I can use for lenses? I’m trying to pass a lens as an argument, but it results in a type error when I try to use view and setl together. Something like this:

let f lens x =
  printfn "%s" (view lens x)
  setl lens "abc" x

The fix suggested by @nikolamilekic should apply here as well.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error: The property '#/settings/X/variables/X' of type object ...
When I try to import a Guide theme, I get the following error: Failed to import theme. The property '#/settings/X/variables/X' of type object ......
Read more >
Optic API for Multi-Model Data Access
This data access function is helpful for testing and debugging. Build a table with two rows and return the row that matches the...
Read more >
Fixing common type problems
This section shows how to fix some of the errors and warnings you might see from the analyzer or an IDE. Static analysis...
Read more >
IBM Informix Messages and Corrections
Earlier versions of the database server do not support raw tables. ... the code in a license-file line does not match the other...
Read more >
stat()--Get File Information
The stat() function gets status information about a specified file and places it in the area of memory pointed to by the buf...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found