Skip to content
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

Possible API Changes #11

Closed
paf31 opened this issue Aug 9, 2014 · 4 comments · Fixed by #12
Closed

Possible API Changes #11

paf31 opened this issue Aug 9, 2014 · 4 comments · Fixed by #12

Comments

@paf31
Copy link
Contributor

paf31 commented Aug 9, 2014

I've wondered for a while whether it would be a good idea to rethink the API for this module. Given that I'm about to write about it for the book, it's probably a good time to raise my concern.

What if we changed the API as follows:

data ForeignError = 
  = TypeMismatch String
  | NoSuchProperty String
  | ...

type F = V [ForeignError]

class ReadForeign a where
  read :: Foreign -> F a
  • Use V instead of Either.
  • Encourage function composition and applicative validation instead of do notation
  • Provide combinators for things like property access:
(.:) :: Foreign -> String -> F Foreign
@paf31 paf31 added the question label Aug 9, 2014
@natefaubion
Copy link
Contributor

Additionally, things like property/index testing and default values would be nice.

@natefaubion
Copy link
Contributor

With the signature (.:) :: Foreign -> String -> F Foreign you have to introduce something like:

parse :: forall a. (ReadForeign a) => F Foreign -> F a
parse = runV invalid read

data TestData = TestData Number Number Number

instance readTestData :: ReadForeign TestData where
  read o = TestData <$> parse (o .: "foo")
                    <*> parse (o .: "bar")
                    <*> parse (o .: "baz")

If you make it (.:) :: forall a. (ReadForeign a) => Foreign -> String -> F a, you can do this:

(.:?) :: forall a. (ReadForeign a) => F Foreign -> String -> F a
(.:?) obj k = runV invalid (\x -> x .: k) obj

instance readForeign :: ReadForeign Foreign where
  read = pure

data TestData = TestData Number Number Number

instance readTestData :: ReadForeign TestData where
  read o = TestData <$> (o .: "foo" .:? "nested")
                    <*> (o .: "bar")
                    <*> (o .: "baz")

Which relates back to #8

@natefaubion
Copy link
Contributor

(I have implemented this library using Data.Validation if you are interested)

@paf31
Copy link
Contributor Author

paf31 commented Aug 17, 2014

I've mocked up another version here: https://github.com/paf31/purescript-foreign-experimental

Having tried pretty hard to get the applicative validation to work with a decent API, and without resorting to invalid Monad instances, I've decided it's not worth the hassle. At this point, I'd just like to tidy things up a little bit.

@paf31 paf31 mentioned this issue Aug 17, 2014
@paf31 paf31 closed this as completed in #12 Aug 20, 2014
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 a pull request may close this issue.

2 participants