Comments (13)
Is there a suggested way around this problem?
I think this is an inference issue. You're right that you'll end up getting a { foo :: Maybe Int, bar :: Maybe String }
, but the instance doesn't seem to know that. If you type your second attempt explicitly, it should work:
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.
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
.
Sure, I'll try to throw something together. Kind of reminds me of Data.Traversable.sequence
.
from purescript-option.
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 MyRecRowsMay
from MyRecRows
, in the below? I don't think so, as I haven't been able to find any means of mapping over RowList at the type level.
type MyRecRows = (foo:: Int, bar:: String)
type MyRecRowsMay = (foo:: Maybe Int, bar:: Maybe String)
type MyRec = Record MyRecRows
type MyRecMay = Record MyRecRowsMay
But, not a big deal, I can always use the slightly more verbose fromRecord
syntax.
Finally, a last question: in order to facilitate easier use of set
, would it be possible to have something like Option.keyedEmpty
, that creates the option with all keys, and associated values set to Nothing
?
Again, not sure how this would be achieved - the problem isn't quite as bad as the above, I think, since we only need to map over SProxies at the value level, but still not sure how to go about it. The alternative seems to be to start with Option.empty
and, for each record type, create a function that manually insert
s Nothing
.
I wonder if purescript-heterogenous could be useful for any of this, but it is way outside my comfort level with types.
from purescript-option.
is there any known way to auto-derive
MyRecRowsMay
fromMyRecRows
, in the below?
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)
in order to facilitate easier use of
set
, would it be possible to have something likeOption.keyedEmpty
, that creates the option with all keys, and associated values set toNothing
?
Sorry, I'm a little confused. What would be the difference between keyedEmpty
and empty
? Like, what would the type of keyedEmpty
be? Higher-level, what are you wanting to do that's hard?
from purescript-option.
The pattern is to Add a type parameter!:
That's super clever!
Sorry, I'm a little confused. What would be the difference between keyedEmpty and empty? Like, what would the type of keyedEmpty be?
empty
and keyedEmpty
would be the same type forall option. Option option
, I think.
Higher-level, what are you wanting to do that's hard?
The difference between empty
and keyedEmpty
would be that the values they give would be different. empty
is truly empty, with no keys added yet. This is significant since set
(and other functions in the API) depend on what keys are already present ("The key must already exist in the option."). It would be really convenient to just be able to use set
to update my record without worrying about this constraint, in my particular use case.
The reason is this: i'm looping over a value of type option with many fields. The first iteration, i could use insert
, and all subsequent iterations could use set
. But it is not very nice to have different behavior in different iterations in a recursive solution.
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!
from purescript-option.
If I'm understanding your particular case correctly, you'll want to use Option.set
the whole time. Using Option.insert
, then Option.set
seems as though you've got a record and you want to control the fields statically. That's fine, but it's a bunch of extra work. Instead, you should be able to create an option with the keys you expect it to have (using Option.empty
) and do your looping:
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 insert
and set
is what they do to the type of an Option _
, not what they do to a value of type Option _
. insert
will always change the type to have more keys. set
will not change which keys are in an Option _
.
E.g.
If we have an Option _
:
start :: Option.Option ( foo :: String )
start = Option.empty
We cannot insert
foo
:
-- 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 foo
key is already in the type of start
. Whether or not the foo
key exists in start
is irrelevant to Option.insert
because it's expecting start
's type to not have the foo
key. It won't type check.
We can set
foo
though:
-- No errors
end :: Option.Option ( foo :: String )
end = Option.set (Data.Symbol.SProxy :: _ "foo") "test" start
We can do this because the foo
key is already in the type of start
. Whether the foo
key exists in start
is irrelevant to Option.set
, it's always going to replace it with the value "test"
.
I don't think it's possible to have one value that behaves the way both Option.insert
and Option.set
behave while still retaining type safety.
The reason Option.insert
and Option.set
are named the way they are is to parallel the values Record.insert
and Record.set
, respectively. In fact, most of Option
has parallels to Record
.
Do you have any suggestions on what might make the distinction between Option.insert
and Option.set
clearer?
from purescript-option.
Oh no! I just looked at the documentation for Option.empty
. The example there is incorrect. Sorry about that. Maybe that's what's causing the confusion? I'll update that and see if I've any more documentation issues.
from purescript-option.
@joneshf Great to hear - I think your doc fix for the empty
example helps clarify. But there remains one point of confusion for me in the docs related to empty
:
Creates an option with no key/values that matches any type of option.
I think this might be more unambiguous if it read:
Creates an option with key/value pairs such that the keys are from the
Option
typeoption
and values are allNothing
Of course, I may still be misunderstanding something, but I think the Option
must have keys for it to work with set
, and this seems to agree with the changes you made and your post above.
from purescript-option.
The pattern is to Add a type parameter!:
That's super clever!
Sorry, I'm a little confused. What would be the difference between keyedEmpty and empty? Like, what would the type of keyedEmpty be?
empty
and keyedEmpty
would be the same type forall option. Option option
, I think.
Higher-level, what are you wanting to do that's hard?
The difference between empty
and keyedEmpty
would be that the values they give would be different. empty
is truly empty, with no keys added yet. This is significant since set
(and other functions in the API) depend on what keys are already present ("The key must already exist in the option."). It would be really convenient to just be able to use set
to update my record without worrying about this constraint, in my particular use case.
The reason is this: i'm looping over a value of type option with many fields. The first iteration, i could use insert
, and all subsequent iterations could use set
. But it is not very nice to have different behavior in different iterations in a recursive solution.
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!
from purescript-option.
Apparently I closed this issue, which was not my intention
from purescript-option.
No worries.
Creates an option with key/value pairs such that the keys are from the
Option
typeoption
and values are allNothing
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?
from purescript-option.
@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?
from purescript-option.
Sorry, I'm really dragging my feet on this one. I thought I'd already merged that PR 😶. I already implemented the sequence
thing. I haven't documented it, so I didn't push it up anywhere. If I get some time I'll try to throw something together soon for it.
from purescript-option.
@joneshf no worries, but wanted to ping back on this as I'm now in a good place to try out the sequence
function in my code base. If you have time to push it as-is to another branch or something, I could test it out somehow
from purescript-option.
Related Issues (12)
- Defining setMay HOT 2
- Discuss possible PR for projection HOT 3
- Is it possible to have a mix of required and optional rows in Record? HOT 16
- Add `purescript-option` to the package set HOT 4
- Document installation
- Provide a way to get any values that exist in an `Option.Option _` or none at all
- Proposal: getAll alternative that returns an Either with errors (missing required fields) HOT 4
- A PR to be PureScript 0.14.x compatible? HOT 4
- Drop support for `purescript-simple-json`
- Documentation for alter function HOT 2
- PureScript 0.15 support HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from purescript-option.