{"action":"opened","issue":{"url":"https://api.github.com/repos/Gabriel439/Haskell-Turtle-Library/issues/119","labels_url":"https://api.github.com/repos/Gabriel439/Haskell-Turtle-Library/issues/119/labels{/name}","comments_url":"https://api.github.com/repos/Gabriel439/Haskell-Turtle-Library/issues/119/comments","events_url":"https://api.github.com/repos/Gabriel439/Haskell-Turtle-Library/issues/119/events","html_url":"https://github.com/Gabriel439/Haskell-Turtle-Library/issues/119","id":115177090,"number":119,"title":"Turtle's `arg` does not support backtracking","user":{"login":"Gabriel439","id":1313787,"avatar_url":"https://avatars.githubusercontent.com/u/1313787?v=3","gravatar_id":"","url":"https://api.github.com/users/Gabriel439","html_url":"https://github.com/Gabriel439","followers_url":"https://api.github.com/users/Gabriel439/followers","following_url":"https://api.github.com/users/Gabriel439/following{/other_user}","gists_url":"https://api.github.com/users/Gabriel439/gists{/gist_id}","starred_url":"https://api.github.com/users/Gabriel439/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Gabriel439/subscriptions","organizations_url":"https://api.github.com/users/Gabriel439/orgs","repos_url":"https://api.github.com/users/Gabriel439/repos","events_url":"https://api.github.com/users/Gabriel439/events{/privacy}","received_events_url":"https://api.github.com/users/Gabriel439/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-11-04T23:53:25Z","updated_at":"2015-11-04T23:53:25Z","closed_at":null,"body":"A `turtle` user reported this when they were attempting to use `Turtle.Options.arg` to simulate sub commands.  Here is the minimal reproducing example of the problem the user encountered:\r\n\r\n```haskell\r\n{-# LANGUAGE OverloadedStrings #-}\r\n\r\nimport qualified Data.Text as Text\r\nimport Turtle\r\n\r\nexample = argMatch \"foo\" empty <|> argMatch \"bar\" empty\r\n\r\nmain = do\r\n    z <- options \"\" example\r\n    print z\r\n\r\nargMatch text =\r\n    arg (\\t -> if t == text then Just t else Nothing)\r\n       (fromString (Text.unpack text))\r\n```\r\n\r\nThis correctly parses the first alternative, but never parses the second alternative:\r\n\r\n```bash\r\n$ ./example foo\r\n\"foo\"\r\n$ ./example bar\r\nUsage: options.hs (FOO | BAR)\r\n\r\nAvailable options:\r\n  -h,--help                Show this help text\r\n```\r\n\r\nThe issue is that if an `arg`-based parser fails it does not allow further processing by other alternatives.  Here is another example using built-in `turtle` argument parsers:\r\n\r\n```haskell\r\nUsage: options.hs (FOO | BAR)\r\n{-# LANGUAGE OverloadedStrings #-}\r\n\r\nimport Turtle\r\n\r\nexample = fmap (format d) (argInt \"foo\" empty) <|> argText \"bar\" empty\r\n\r\nmain = do\r\n    z <- options \"\" example\r\n    print z\r\n```\r\n\r\nA user might expect this to fall back on parsing a `Text` if `Int` parsing fails, but it does not:\r\n\r\n```bash\r\n$ ./example 5\r\n\"5\"\r\n$ ./example five\r\nUsage: options.hs (FOO | BAR)\r\n\r\nAvailable options:\r\n  -h,--help                Show this help text\r\n```"}}