purescript-foreign icon indicating copy to clipboard operation
purescript-foreign copied to clipboard

OneOf?

Open justinwoo opened this issue 6 years ago • 4 comments

Feels like we probably already have a oneOf function that can make sure that not all branches are evaluated at once (to ensure efficient as-needed parsing), since using alt naively can lead to really really slow decoding, but I honestly don't know where it is. Is there something I'm missing that already implements this?:

oneOf :: forall f a
   . Foldable f
  => f (Foreign -> F a)
  -> Foreign
  -> F a
oneOf f js = go (fromFoldable f) js
  where
    go (read : xs) js = do
      case runExcept (read js) of
        Right pv -> pure pv
        Left e -> do
          case runExcept (go xs js) of
            Right pv' -> pure pv'
            Left e' -> throwError (e <> e')
    go Nil _ = do
      throwError $ pure (ForeignError "No more parsers to attempt in oneOf")

If not, I could PR this, but feels like it probably exists as a simple combination of some operators.

justinwoo avatar Nov 18 '17 23:11 justinwoo

This looks good! Perhaps you want to use foldl (or even foldl1?) instead, to avoid copying the list?

go prev next = case runExcept prev of
  Left e -> case runExcept (next js) of
    Left e' -> throwError (e <> e')
    r -> r
  r -> r

But yeah, it's hard ... we need laziness ~dreamy sigh~

MonoidMusician avatar Nov 18 '17 23:11 MonoidMusician

If we had a lazy Either, we could use regular oneOf, right?

paf31 avatar Nov 18 '17 23:11 paf31

newtype Decoder = Decoder (Foreign -> F a) would probably work – just making the return type lazy would be hard to use, I think.

MonoidMusician avatar Nov 18 '17 23:11 MonoidMusician

Decoder does sound useful anyway.

paf31 avatar Nov 18 '17 23:11 paf31