-
Notifications
You must be signed in to change notification settings - Fork 15
Question on using ToRecord #2
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
Comments
I think this is an inference issue. You're right that you'll end up getting a type MyRec = Record (foo :: Maybe Int, bar :: Maybe String)
recTest :: Opt.Option MyRecRows -> String
recTest myRecOpt = (show fooInt)
<> "\n"
<> (show $ Opt.get(SProxy :: _ "bar") myRecOpt)
where
fooInt :: Maybe Int
fooInt = ((Opt.toRecord' myRecOpt) :: MyRec).foo I'm not entirely sure if this is an issue with this package or something in the type checker. I'll see if the fundeps can be altered to address this.
Sure, I'll try to throw something together. Kind of reminds me of |
Great! wasn't sure if it was possible. And yes, the explicit annotation fixes it. I guess this brings up another question: is there any known way to auto-derive
But, not a big deal, I can always use the slightly more verbose Finally, a last question: in order to facilitate easier use of I wonder if purescript-heterogenous could be useful for any of this, but it is way outside my comfort level with types. |
The pattern is to Add a type parameter!: type MyRecRows (a :: Type -> Type)
= ( foo :: a Int
, bar :: a String
)
type Identity a
= a
type MyRec
= Record (MyRecRows Identity)
type MyRecMay
= Record (MyRecRows Maybe)
Sorry, I'm a little confused. What would be the difference between |
That's super clever!
The difference between The reason is this: i'm looping over a value of type option with many fields. The first iteration, i could use Of course, I may be misunderstanding some existing functionality, but hopefully I've done a better job explaining today now that I'm more well rested! |
If I'm understanding your particular case correctly, you'll want to use baz :: Option.Option ( foo :: Int, bar :: String )
baz = Option.empty
qux :: Option.Option ( foo :: Int, bar :: String )
qux = Option.set (Data.Symbol.SProxy :: _ "foo") 31 baz This might be a documentation issue. The difference between E.g. start :: Option.Option ( foo :: String )
start = Option.empty We cannot -- Will have an error about duplicate rows or types not unifying or something.
this_will_not_type :: Option.Option ( foo :: String )
this_will_not_type = Option.insert (Data.Symbol.SProxy :: _ "foo") "test" start The We can -- No errors
end :: Option.Option ( foo :: String )
end = Option.set (Data.Symbol.SProxy :: _ "foo") "test" start We can do this because the I don't think it's possible to have one value that behaves the way both The reason Do you have any suggestions on what might make the distinction between |
Oh no! I just looked at the documentation for |
@joneshf Great to hear - I think your doc fix for the
I think this might be more unambiguous if it read:
Of course, I may still be misunderstanding something, but I think the |
That's super clever!
The difference between The reason is this: i'm looping over a value of type option with many fields. The first iteration, i could use Of course, I may be misunderstanding some existing functionality, but hopefully I've done a better job explaining today now that I'm more well rested! |
Apparently I closed this issue, which was not my intention |
No worries.
Your suggestion points toward different terminology making it clearer what these things are used for. Maybe the issue is that the terminology is too loose and a more explicit distinction between run-time and compile-time would be helpful? |
@joneshf Yes, I think you are right about the terminology maybe being possible to be clearer distinguishing between values and types, but I think the doc fix update PR is good as is. I can take a stab at trying to update the docs in a second pass based on my improved understanding, and hopefully that will also help fill in some remaining gaps, if there are any. Regarding coming up with an analogue to sequence as discussed above, this is a bit beyond my comfort zone, but wonder if using something like this could be useful? |
Sorry, I'm really dragging my feet on this one. I thought I'd already merged that PR 😶. I already implemented the |
@joneshf no worries, but wanted to ping back on this as I'm now in a good place to try out the |
As requested in #2, we'd like some way to get every value if they all exist. If anything doesn't exist, we'd like the whole thing to fail. This is similar in spirit to `Data.Traversable.sequence`, but monomorphized to `Data.Maybe.Maybe` as the `Applicative`. Since it also shares quite a bit in common with `get`, we name it accordingly. This naming hints that there might be more to the family of get* values. We might think about a way to get a subset of keys from an option. Or, we might want a way to get a subset of keys with default values. Something to think about for the future.
In the following example, I get an instance not found error for
ToRecordOption
:One point of confusion is that I think this should be returning a "maybe-fied" record, so I should really have
fooInt :: Maybe Int
:But the error becomes worse:
Is there a suggested way around this problem?
Also, I wonder if it might be possible to have another function,
toRecordMay
or some such, that goes fromOption opt
->Maybe rec
, such that we get a populated record only if every field of the record (or, perhaps easier to reason about: every field in the option) is notNothing
*, otherwise just returnNothing
. I think this could be highly useful for accumulating state incrementally.*One exception is that if some fields of the output record are themselves
Maybe
values, but really we would still be requiring a value isJust x
wherex
might beNothing
. Maybe this is worthy of its own issue to discuss separately.The text was updated successfully, but these errors were encountered: