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

More natural takeWhile analogue? #455

Open
treeowl opened this issue May 30, 2023 · 2 comments
Open

More natural takeWhile analogue? #455

treeowl opened this issue May 30, 2023 · 2 comments

Comments

@treeowl
Copy link
Collaborator

treeowl commented May 30, 2023

We have

takeWhile :: Dupable a => (a %1 -> Bool) -> [a] %1 -> [a]
takeWhile _ [] = []
takeWhile p (x : xs) =
  dup2 x & \(x', x'') ->
    if p x'
      then x'' : takeWhile p xs
      else (x'', xs) `lseq` []

Should we add a version that (a bit like mapMaybe for filter) relaxes the constraint while adding flexibility?

mapWhileJust :: Consumable a => (a %1 -> Maybe b) -> [a] %1 -> [b]
mapWhileJust _ [] = []
mapWhileJust p (x : xs) =
  case p x of
    Nothing -> xs `lseq` []
    Just x' -> x' : mapWhileJust p xs

Unfortunately, I don't see any similarly intuitive analogue of dropWhile.

@aspiwack
Copy link
Member

aspiwack commented Jun 1, 2023

This is a good point. I think it's quite related to the discussion on #447 , isn't it? It's all about “what are natural things we can do with linear values”. The more we ask of Consumable, Dupable, etc… the less natural the function is.

Just like for sorting and stuff, dropWhile seems to want to know something about a without consuming a (or consuming a only in some cases). And it does all feel kind of icky in the world of linear types.

I have the feeling at the back of my head that, yes, there is some good principle that would cover a lot of theses cases. But I don't know. Of course, anything that changes the size of a list is going to have some amount of unnaturalness. But can we minimise? mapWhileJust is clearly an improvement.

@treeowl
Copy link
Collaborator Author

treeowl commented Jun 12, 2023

Probably the biggest generalization is of span.

spanly ::  (a %1 -> Either c b) -> [a] %1 -> ([b], Maybe (c, [a]))
spanly f [] = ([], Nothing)
spanly f (x : xs) = case f x of
  Right x' -> case spanly f xs of
    (bs, mcas) -> (x' : bs, mcas)
  Left x' -> ([], Just (x', xs))

Awkwardly, though, that's not lazy, and therefore really wants to produce a stream instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants