Skip to content

Sum tags map #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Sum tags map #79

wants to merge 4 commits into from

Conversation

wclr
Copy link

@wclr wclr commented Apr 17, 2025

This PR adds typed tag mapping feature discussed earlier.

sum'   
  { "Foo": "foolery"
  , "Bar": "bar"
  , "Baz": "bazinga"
  }
  { "Foo": ...
   , "Bar": ...
   , "Baz": ..
  }

I wonder what do you think about it, API and implementation. @garyb @m-bock

@m-bock
Copy link
Contributor

m-bock commented Apr 20, 2025

How about this API:

sum' 
  { "Foo": { label: "foolery", codec: ... }
  , "Bar": { label: "bar", codec: ... }
  , "Baz": { label: "bazinga", codec: ... }
  }

Maybe in the future there may be more options "per case", then this could be easily extended.


class GTagsMap ∷ ∀ k. Row Type → k → Constraint
class GTagsMap r rep where
gTagsMap ∷ Proxy rep → Record r → Object String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about defining the class without method if the only thing it does is unsafe coerce?
This operation could be done once in sumWith where its called.

Another thought: You could avoid the unsafeCoerce if you add the Homogeneous constraint and then use: https://pursuit.purescript.org/packages/purescript-foreign-object/4.1.0/docs/Foreign.Object#v:fromHomogeneous

Copy link
Author

@wclr wclr Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially we could construct this Object safely, also we could use Map, Object and unsafeCoerce just for performance reason. Object.fromHomogeneous is unsafeCoerce anyway, though if we add Homogeneous r String constraint we can use fromHomogeneous. I also thought about how this would work in the new codec-json lib, should we convert this mapping record to safely constructed Map String String or unsafely coerced JObject (for speed)?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought about how this would work in the new codec-json lib, should we convert this mapping record to safely constructed Map String String or unsafely coerced JObject (for speed)?

(I know this isn't necessarily the place to discuss it just here, but unsafeCoerce is not allowed in codec-json - we can implement something in the FFI to do the conversion and just have it return the input, so essentially unsafeCoerce, but using unsafeCoerce directly is a no-go. The purpose of JObject, JArray, etc. is to uncouple the representation of JSON from the representation the language uses for map-like and array-like things, so that in theory it's usable by other backends too where the shared representation may not be viable).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, really this tags' map is constructed once when the codec is declared, so I believe we can just use Map String String (if Object String is not available) here, it shouldn't have much impact with Map.lookup when converting tags.

@wclr
Copy link
Author

wclr commented Apr 21, 2025

How about this API:

sum' 
  { "Foo": { label: "foolery", codec: ... }
  , "Bar": { label: "bar", codec: ... }
  , "Baz": { label: "bazinga", codec: ... }
  }

Maybe in the future there may be more options "per case", then this could be easily extended.

I am not in favour of such complicated API without paticular (potential) need, what per case options else could be needed? I think typed tags mapping is supposed to be straightforward. TagsMap for tags, GCases (codecs) for values, I don't think there is a reason to compilcate more -)

Another thought it could be a more dynamic option, function instead of const String:

sum'   
  { "Foo": const "foolery"
  , "Bar": identity
  , "Baz": identity
  }

@m-bock
Copy link
Contributor

m-bock commented Apr 22, 2025

@wclr Got your point. Maybe the API you suggests makes more sense.
Yes, a function String -> String I would prefer, too instead of just String.
Regarding the "unsafe coerce", I just suggest to only perform it at one place.

What about the name sum'? Can we find something more descriptive?

@wclr
Copy link
Author

wclr commented Apr 23, 2025

I'm not sure what would be a good descriptive naming heresumWithTagsWith -)? ~With is a good convention for passing options, ' reasons are more ambiguous, just another version. Currently I think it is ok in the context, sum is more commonly used for working with only values, sum' for working with tags and values, considering that needed API capabilities are covered.

I wonder if we can come up with a more appropriate variant.

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

Successfully merging this pull request may close these issues.

3 participants