-
Notifications
You must be signed in to change notification settings - Fork 68
add sum encoding and handling for sum types of unary constructors #26
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
Conversation
db4dee6 to
8a41b83
Compare
|
Alternatively, I wrote this up where I've defined a function to provide instances specifically for sum types of unary constructors: justinwoo@179831c. Should I squash this here instead of using the conditional version in this branch? I'd really like to also provide some |
|
What do you think about making a separate generic decoding/encoding function for enums like this? That way we could actually enforce using the type system that they only accept "enum types". |
8a41b83 to
73155eb
Compare
|
I squashed my separate genericDecodeUnaryConstructors and genericEncodeUnaryConstructors functions into this one. Like my comment before though, while it doesn't match any instances for reps that aren't Sum or Constructor NoArg, I can't add Fail constraints without having overlapping instance warnings, so it could be a little confusing to use. But that fail constraint can wait until something with instance chains gets figured out. |
| @@ -0,0 +1,62 @@ | |||
| module SumEncoding where | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Module name is incomplete here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, oops
| => GenericDecodeUnarySum (Constructor name NoArguments) where | ||
| decodeSum {constructorTagTransform} f = do | ||
| tag <- constructorTagTransform <$> readString f | ||
| unless (constructorTagTransform tag == ctorName) $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You apply constructorTagTransform twice.
| fail (ForeignError ("Expected " <> show ctorName <> " tag for unary constructor literal " <> ctorName)) | ||
| pure $ Constructor NoArguments | ||
| where | ||
| ctorName = constructorTagTransform $ reflectSymbol (SProxy :: SProxy name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here
|
Just add a Also, can we use the term "enum"? I think it's pretty common for this type of data. |
73155eb to
67c61e5
Compare
|
Updated. I added the instances, though, I haven't been able to come up with ways to reach those without a constructor constraint. |
67c61e5 to
321dd09
Compare
|
Yes, you would need to write several instances for |
src/Data/Foreign/Generic/Enum.purs
Outdated
| encodeEnum _ _ = unsafeCrashWith "unreachable encodeEnum was reached." | ||
|
|
||
| instance recGenericEncodeEnum | ||
| :: Fail """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pull the error messages out into a single common type synonym?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I wouldn't be able to change the wording right? I do want to put what kind of type they were trying to plug in here for a more relevant error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just say "doesn't work with constructors with arguments" though? Records and products are both types of arguments. Do you not think it's clear enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that's fine. I'll switch them over then
|
Another option is to use |
8bd5849 to
78bf86d
Compare
src/Data/Foreign/Generic/Types.purs
Outdated
| { sumEncoding :: SumEncoding | ||
| , unwrapSingleConstructors :: Boolean | ||
| , unwrapSingleArguments :: Boolean | ||
| , constructorTagTransform :: String -> String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this go into TaggedObject?
src/Data/Foreign/Generic/Enum.purs
Outdated
| decodeEnum opts f = Inl <$> decodeEnum opts f <|> Inr <$> decodeEnum opts f | ||
|
|
||
| instance ctorNoArgsGenericDecodeEnum | ||
| :: (IsSymbol name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parens are redundant here.
f8c910b to
eef91d7
Compare
|
Updated this. Like we found on Slack, I couldn't find out how to make a synonym actually work at the usage site of the Fail instances, and then I moved the tag transform into SumEncoding. |
src/Data/Foreign/Generic/Enum.purs
Outdated
|
|
||
| instance ctorArgumentGenericEncodeEnum | ||
| :: Fail """ | ||
| genericEncodeEnum cannot be used with constructors with arguments, as it is meant to work with string literal "Enums", Sum types of no-argument constructors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would still trim this down a bit and put the stuff about enums into the documentation for the classes.
07e68b7 to
0dc8f05
Compare
|
Wrote up some docstrings with a small code example in each top level method, with just short descriptions of the typeclasses and the instance errors. |
src/Data/Foreign/Generic/Enum.purs
Outdated
| => GenericDecodeEnum (Constructor name NoArguments) where | ||
| decodeEnum {sumEncoding: TaggedObject {constructorTagTransform}} f = do | ||
| tag <- readString f | ||
| unless (constructorTagTransform tag == ctorName) $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong way around here, surely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, yeah. the ctorname is already transformed, but i guess transforming the tag itself is kinda wonky...
src/Data/Foreign/Generic/Enum.purs
Outdated
| ctorName = constructorTagTransform $ reflectSymbol (SProxy :: SProxy name) | ||
|
|
||
| instance ctorArgumentGenericDecodeEnum | ||
| :: Fail """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put these Fail constraints on one line and just use a single error message in a type declaration.
src/Data/Foreign/Generic/Enum.purs
Outdated
| :: forall a rep | ||
| . Generic a rep | ||
| => GenericDecodeEnum rep | ||
| => Options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're only using constructorTagTransform here, let's only require a record with that one field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use row polymorphism if we want to support more fields.
|
Sorry for the delay, I have a few more comments. |
0dc8f05 to
b69b255
Compare
|
I updated this, but I still cannot get the type alias string to properly work on my machine for the Fail constraint. I will get "No type class instance was found for Fail GenericEncodeDecodeFailMessage"... |
|
Ok, I'd prefer one of the following then:
|
Adds constructor tag transform so that users can customize the tag as needed
b69b255 to
e42b38a
Compare
|
Pushed an update to do no 2. I'll try to remember to come back to this when we get purescript/purescript#2972 fixed. |
|
Great, thanks for all the work on this! |
| "purescript-symbols": "^3.0.0" | ||
| "purescript-proxy": "^2.1.0", | ||
| "purescript-symbols": "^3.0.0", | ||
| "purescript-strings": "^3.2.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like you're using this any more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😨
|
Thanks!!! Now I need to remember to update my howto guides and start making some noise about enum sum type support 😄 |
fixes #25
uses some flags to determine casing and then uses these flags in encoding/decoding
updated excerpt: