Closed
Description
Recently I used List.Lazy
and my expectation was that parser take 2 (many (char '0'))
Will try to match character 0
maximum 2 times. But it's actually trying to match 0
until it fails. So if input to parser is 0000000
it will consume all of 0
-s and result will be list of two 0
-s.
To solve this issue I have implemented takeSome
and takeMany
for normal List
:
-- | Attempt a computation `n` times, requiring at least one success.
-- |
-- | The `Lazy` constraint is used to generate the result lazily, to ensure
-- | termination.
takeSome :: forall f a. Alternative f => Lazy (f (List a)) => Int -> f a -> f (List a)
takeSome 0 _ = pure Nil
takeSome n v = Cons <$> v <*> defer (\_ -> takeMany (n - 1) v)
-- | Attempt a computation `n` times, returning as many successful results
-- | as possible (possibly zero).
-- |
-- | The `Lazy` constraint is used to generate the result lazily, to ensure
-- | termination.
takeMany :: forall f a. Alternative f => Lazy (f (List a)) => Int -> f a -> f (List a)
takeMany 0 _ = pure Nil
takeMany n v = takeSome n v <|> pure Nil
If Infinity
was member of Int
then:
some = takeSome Infinity
many = takeMany Infinity
This issue is not strictly related to Parser but i think it could be useful for parsers.
What you think if we define this functions for List/Array/...
.
We can have on internal definition take{Some,Many}
which are taking Number
(to allow use of Infinity
) and define some, many, takeSome and takeMany in terms of them.
takeSome = toNumber >>> takeSome_
some = takeSome_ Infinity
takeMeny = toNumber >>> takeMeny_
meny = takeMeny_ Infinity
Metadata
Metadata
Assignees
Labels
No labels