Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Traits for the greater good #270

Open
mikearnaldi opened this issue Mar 11, 2023 · 3 comments
Open

Traits for the greater good #270

mikearnaldi opened this issue Mar 11, 2023 · 3 comments

Comments

@mikearnaldi
Copy link
Member

We currently have the following traits:

  • Hash : to represents objects that can be hashed
  • Equal : to represent equality between objects

We can see traits as typeclasses that are directly implemented in the data rather than presented as separated instances, they have the advantage of not requiring to pass explicitly instances and can make DX better.

There are other scenarios that came up as useful, those are:

  • Compare : like a partial order that enables implementation of things like sortBy(array, p => [p.age, p.name]) without manually constructing an Order instance (that one should be able to still do)
  • *Copy : encodes the ability to copy an object to a separated instance
  • *Index : enables indexed access and updates over a structure that is indexed (e.g. Chunk, HashMap, etc)

Note: The ones marked with * are coming from requirements in optics.

@mikearnaldi
Copy link
Member Author

cc @patroza @gcanti @IMax153 @pigoz

@patroza
Copy link
Member

patroza commented Mar 11, 2023

so far what seems to work well is Object.setPrototypeOf(copy, Object.getPrototypeOf(original)).
for Data.struct, classes in general, and for Data.Class etc.
Perhaps using that as a default, with the ability to override via a copy trait, would be a good way forward.

See https://github.com/patroza/optic/pull/1/files

@patroza
Copy link
Member

patroza commented Mar 12, 2023

cloning with private fields gets a little hairy...

  test("some private", () => {
    class ABC {
      [Optic.cloneTrait](a: any) {
        const cl = new ABC(a.a, a.b)
        cl.#test = this.#test
        return cl // Object.assign(Object.create(this), a)
      }
      #test: number
      constructor(readonly a: number, readonly b: number) {
        this.#test = 1
      }

      set test(v: number) {
        this.#test = v
      }

      get test() {
        return this.#test
      }
    }
    const opt = Optic.id<ABC>()
    const v = new ABC(1, 2)
    v.test = 2

    const v2 = Optic.replace(opt.at("a"))(1)(v)
    expect(v.test).toBe(2)
    expect(v2.test).toBe(2)
  })

but its a general problem with private fields.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants