sanctuary-js / sanctuary

:see_no_evil: Refuge from unsafe JavaScript
https://sanctuary.js.org
MIT License
3.03k stars 94 forks source link

lawful lenses #177

Open davidchambers opened 8 years ago

davidchambers commented 8 years ago

R.lensProp and R.lensIndex aren't quite lawful, as @scott-christopher explained in https://github.com/ramda/ramda/issues/1281#issuecomment-209444109.

Scott, have you any interest in working on Sanctuary equivalents of Ramda's lens functions, which would use the Maybe type where appropriate to satisfy the lens laws?

masaeedu commented 6 years ago

Wouldn't the following lens be lawful?

const fail = e => { throw new TypeError(e) }
const lensProp = p => ({
  view: o => o.hasOwnProperty(p) ? o[p] : fail(`Missing property ${p}`),
  update: x => o => o.hasOwnProperty(p) ? { ...o, [p]: x } : fail(`Missing property ${p}`)
})
davidchambers commented 6 years ago

I think so, @masaeedu, given the strictness of S.prop. In fact, using S.prop would simplify the definitions of view and update.

masaeedu commented 6 years ago

@davidchambers Sweet. So basically const lensProp = p => ({ view: S.prop(p), update: S.insert(p) })

scott-christopher commented 6 years ago

Apologies, I completely missed this issue ... 2 years ago. I'd be happy to help migrate https://github.com/flunc/optics over to become a Sanctuary project if there's interest.

The existing atObject :: String -> LensP (Object a) (Maybe a) seems to already fit the bill for this specific request.

As it stands, the library is void of documentation and there has been no focus on performance, but these are things we can change :)

davidchambers commented 6 years ago

We needn't move flunc/optics to the @sanctuary-js namespace, though if you would like to do this, @scott-christopher, I'd be very happy for you to do so. I could not at this point commit much of my time to the effort.

protoEvangelion commented 4 years ago

@davidchambers is there anything on the roadmap still for implementing lenses?

coodoo commented 4 years ago

As a side note, what's the story for lens/optics from sanctuary at this moment? Seemed there's only getter (like gets and props), but no setters?

davidchambers commented 4 years ago

@protoEvangelion and @coodoo, lenses will be the next major addition to Sanctuary.

As it may be of interest, I will share the backstory. In order to define van Laarhoven lenses, which have the desirable property of being compatible with S.compose, we need two types: Identity a and Constant a b. The former exists as sanctuary-identity; the latter will exist once sanctuary-js/sanctuary-constant#1 has been merged. As I was working on sanctuary-constant I was also working on fantasyland/fantasy-land#315, a proposal that will, if accepted, necessitate changes to every Fantasy Land -compliant ADT. It seemed sensible at the time to release a new major version of the Fantasy Land specification before publishing any new ADT packages.

In mid 2019 I started a full-time job, as I was running out of money. My ambitious plans may have made sense when I had a lot of time to devote to Sanctuary, but when the demands on my time increased I should have reconsidered them. The Fantasy Land changes are themselves several weeks of full-time work, as they involve updating fantasy-laws and the many Sanctuary ADTs.

Let's finalize and merge sanctuary-js/sanctuary-constant#1 without waiting for fantasyland/fantasy-land#315. We will then have what we need to define S.lens, S.view, S.over, and S.set. Later, once FL5 has been published, we will release sanctuary-constant@2.0.0.

Avaq commented 4 years ago

In order to define van Laarhoven lenses, which have the desirable property of being compatible with S.compose, we need two types: Identity a and Constant a b.

As remarked in Gitter, we don't necessarily have to use van Laarhoven encoding to get lenses to work with S.compose. Instead we can use any object with Semigroupoid implemented. This removes the need for the Identity a and Constant a b types.

The downside of this approach is that these lenses will not work with function-specialized compose functions from other sources, or if JavaScript would ever introduce a composition operator I don't imagine it will follow the Fantasy Land Semigroupoid spec.