Giter Site home page Giter Site logo

Comments (13)

joneshf avatar joneshf commented on August 22, 2024

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 from Option 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 not Nothing*, otherwise just return Nothing.

Sure, I'll try to throw something together. Kind of reminds me of Data.Traversable.sequence.

from purescript-option.

bbarker avatar bbarker commented on August 22, 2024

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 inserts 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.

joneshf avatar joneshf commented on August 22, 2024

is there any known way to auto-derive MyRecRowsMay from MyRecRows, 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 like Option.keyedEmpty, that creates the option with all keys, and associated values set to Nothing?

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.

bbarker avatar bbarker commented on August 22, 2024

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.

joneshf avatar joneshf commented on August 22, 2024

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.

joneshf avatar joneshf commented on August 22, 2024

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.

bbarker avatar bbarker commented on August 22, 2024

@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 type option and values are all Nothing

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.

bbarker avatar bbarker commented on August 22, 2024

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.

bbarker avatar bbarker commented on August 22, 2024

Apparently I closed this issue, which was not my intention

from purescript-option.

joneshf avatar joneshf commented on August 22, 2024

No worries.

Creates an option with key/value pairs such that the keys are from the Option type option and values are all Nothing

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.

bbarker avatar bbarker commented on August 22, 2024

@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.

joneshf avatar joneshf commented on August 22, 2024

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.

bbarker avatar bbarker commented on August 22, 2024

@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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.