{"action":"closed","number":68,"pull_request":{"url":"https://api.github.com/repos/simonmar/alex/pulls/68","id":39212367,"html_url":"https://github.com/simonmar/alex/pull/68","diff_url":"https://github.com/simonmar/alex/pull/68.diff","patch_url":"https://github.com/simonmar/alex/pull/68.patch","issue_url":"https://api.github.com/repos/simonmar/alex/issues/68","number":68,"state":"closed","locked":false,"title":"Add functionality for using typeclasses in lexers","user":{"login":"emc2","id":1473226,"avatar_url":"https://avatars.githubusercontent.com/u/1473226?v=3","gravatar_id":"","url":"https://api.github.com/users/emc2","html_url":"https://github.com/emc2","followers_url":"https://api.github.com/users/emc2/followers","following_url":"https://api.github.com/users/emc2/following{/other_user}","gists_url":"https://api.github.com/users/emc2/gists{/gist_id}","starred_url":"https://api.github.com/users/emc2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emc2/subscriptions","organizations_url":"https://api.github.com/users/emc2/orgs","repos_url":"https://api.github.com/users/emc2/repos","events_url":"https://api.github.com/users/emc2/events{/privacy}","received_events_url":"https://api.github.com/users/emc2/received_events","type":"User","site_admin":false},"body":"This pull request adds functionality for generating lexers that are amenable to the use of type classes.  There are two primary usage patterns for this: 1) Use of type classes in the token types and 2) Use of type classes in monads.\r\n\r\nThis patch adds three new directives to the lexer file format: `%token`, `%typeclass`, and `%action`.  `%action` is allowed only if no wrapper directive is given, and specifies the type of actions.  `%token` is allowed only if a directive is given, and specifies the type of the tokens (since the wrapper type implies a particular type for actions).  If these directives are given, then type signatures will be generated in the generated code.\r\n\r\nAdditionally, the `%typeclass` directive is allowed if `%action` or `%token` is given, and specifies one or more type classes that will be present in the type signatures.\r\n\r\nThis patch handles all documented wrappers, as well as lexers with no wrapper, including the bytecode variations.  It makes a minor alteration to the alex_accept array, splitting out the actions into a separate array (this is necessary to avoid an ambiguous type variable that arises when both type classes and contexts are used).\r\n\r\nWith this patch, it is possible to generate a lexer with the following action:\r\n\r\n`literal :: Read s => String -> Token s`\r\n`literal = Literal . read`\r\n\r\nWith the current version of Alex, this would generate compile errors.  It is also possible to do something like this (with a home-made monadic lexer):\r\n\r\n`badChars :: MonadLexerErrors m => AlexPosn -> String -> m Token`\r\n`badChars pos chars =`\r\n`  do`\r\n`    reportError $ \"invalid characters \" ++ chars ++ \" at \" show pos`\r\n`    alexMonadScan`\r\n\r\nThis use of monad type classes is particularly useful, as it allows the same lexer to work in a wide variety of contexts.","created_at":"2015-07-04T20:03:31Z","updated_at":"2016-02-02T16:20:00Z","closed_at":"2016-02-02T16:19:59Z","merged_at":"2016-02-02T16:19:59Z","merge_commit_sha":"4d79187063865c30128111286a14c2ff37d91aa8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/simonmar/alex/pulls/68/commits","review_comments_url":"https://api.github.com/repos/simonmar/alex/pulls/68/comments","review_comment_url":"https://api.github.com/repos/simonmar/alex/pulls/comments{/number}","comments_url":"https://api.github.com/repos/simonmar/alex/issues/68/comments","statuses_url":"https://api.github.com/repos/simonmar/alex/statuses/d9e530640561ecedded8ad000f18e9ae793a468f","head":{"label":"emc2:master","ref":"master","sha":"d9e530640561ecedded8ad000f18e9ae793a468f","user":{"login":"emc2","id":1473226,"avatar_url":"https://avatars.githubusercontent.com/u/1473226?v=3","gravatar_id":"","url":"https://api.github.com/users/emc2","html_url":"https://github.com/emc2","followers_url":"https://api.github.com/users/emc2/followers","following_url":"https://api.github.com/users/emc2/following{/other_user}","gists_url":"https://api.github.com/users/emc2/gists{/gist_id}","starred_url":"https://api.github.com/users/emc2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emc2/subscriptions","organizations_url":"https://api.github.com/users/emc2/orgs","repos_url":"https://api.github.com/users/emc2/repos","events_url":"https://api.github.com/users/emc2/events{/privacy}","received_events_url":"https://api.github.com/users/emc2/received_events","type":"User","site_admin":false},"repo":{"id":37351791,"name":"alex","full_name":"emc2/alex","owner":{"login":"emc2","id":1473226,"avatar_url":"https://avatars.githubusercontent.com/u/1473226?v=3","gravatar_id":"","url":"https://api.github.com/users/emc2","html_url":"https://github.com/emc2","followers_url":"https://api.github.com/users/emc2/followers","following_url":"https://api.github.com/users/emc2/following{/other_user}","gists_url":"https://api.github.com/users/emc2/gists{/gist_id}","starred_url":"https://api.github.com/users/emc2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emc2/subscriptions","organizations_url":"https://api.github.com/users/emc2/orgs","repos_url":"https://api.github.com/users/emc2/repos","events_url":"https://api.github.com/users/emc2/events{/privacy}","received_events_url":"https://api.github.com/users/emc2/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/emc2/alex","description":"A lexical analyser generator for Haskell","fork":true,"url":"https://api.github.com/repos/emc2/alex","forks_url":"https://api.github.com/repos/emc2/alex/forks","keys_url":"https://api.github.com/repos/emc2/alex/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emc2/alex/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emc2/alex/teams","hooks_url":"https://api.github.com/repos/emc2/alex/hooks","issue_events_url":"https://api.github.com/repos/emc2/alex/issues/events{/number}","events_url":"https://api.github.com/repos/emc2/alex/events","assignees_url":"https://api.github.com/repos/emc2/alex/assignees{/user}","branches_url":"https://api.github.com/repos/emc2/alex/branches{/branch}","tags_url":"https://api.github.com/repos/emc2/alex/tags","blobs_url":"https://api.github.com/repos/emc2/alex/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emc2/alex/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emc2/alex/git/refs{/sha}","trees_url":"https://api.github.com/repos/emc2/alex/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emc2/alex/statuses/{sha}","languages_url":"https://api.github.com/repos/emc2/alex/languages","stargazers_url":"https://api.github.com/repos/emc2/alex/stargazers","contributors_url":"https://api.github.com/repos/emc2/alex/contributors","subscribers_url":"https://api.github.com/repos/emc2/alex/subscribers","subscription_url":"https://api.github.com/repos/emc2/alex/subscription","commits_url":"https://api.github.com/repos/emc2/alex/commits{/sha}","git_commits_url":"https://api.github.com/repos/emc2/alex/git/commits{/sha}","comments_url":"https://api.github.com/repos/emc2/alex/comments{/number}","issue_comment_url":"https://api.github.com/repos/emc2/alex/issues/comments{/number}","contents_url":"https://api.github.com/repos/emc2/alex/contents/{+path}","compare_url":"https://api.github.com/repos/emc2/alex/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emc2/alex/merges","archive_url":"https://api.github.com/repos/emc2/alex/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emc2/alex/downloads","issues_url":"https://api.github.com/repos/emc2/alex/issues{/number}","pulls_url":"https://api.github.com/repos/emc2/alex/pulls{/number}","milestones_url":"https://api.github.com/repos/emc2/alex/milestones{/number}","notifications_url":"https://api.github.com/repos/emc2/alex/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emc2/alex/labels{/name}","releases_url":"https://api.github.com/repos/emc2/alex/releases{/id}","deployments_url":"https://api.github.com/repos/emc2/alex/deployments","created_at":"2015-06-13T00:54:36Z","updated_at":"2016-01-27T21:17:42Z","pushed_at":"2016-01-27T21:17:40Z","git_url":"git://github.com/emc2/alex.git","ssh_url":"git@github.com:emc2/alex.git","clone_url":"https://github.com/emc2/alex.git","svn_url":"https://github.com/emc2/alex","homepage":"http://www.haskell.org/alex","size":562,"stargazers_count":0,"watchers_count":0,"language":"Haskell","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"simonmar:master","ref":"master","sha":"5480ff8e97706c5642f3eca38e7e308aaf0f4bfd","user":{"login":"simonmar","id":609606,"avatar_url":"https://avatars.githubusercontent.com/u/609606?v=3","gravatar_id":"","url":"https://api.github.com/users/simonmar","html_url":"https://github.com/simonmar","followers_url":"https://api.github.com/users/simonmar/followers","following_url":"https://api.github.com/users/simonmar/following{/other_user}","gists_url":"https://api.github.com/users/simonmar/gists{/gist_id}","starred_url":"https://api.github.com/users/simonmar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/simonmar/subscriptions","organizations_url":"https://api.github.com/users/simonmar/orgs","repos_url":"https://api.github.com/users/simonmar/repos","events_url":"https://api.github.com/users/simonmar/events{/privacy}","received_events_url":"https://api.github.com/users/simonmar/received_events","type":"User","site_admin":false},"repo":{"id":2032368,"name":"alex","full_name":"simonmar/alex","owner":{"login":"simonmar","id":609606,"avatar_url":"https://avatars.githubusercontent.com/u/609606?v=3","gravatar_id":"","url":"https://api.github.com/users/simonmar","html_url":"https://github.com/simonmar","followers_url":"https://api.github.com/users/simonmar/followers","following_url":"https://api.github.com/users/simonmar/following{/other_user}","gists_url":"https://api.github.com/users/simonmar/gists{/gist_id}","starred_url":"https://api.github.com/users/simonmar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/simonmar/subscriptions","organizations_url":"https://api.github.com/users/simonmar/orgs","repos_url":"https://api.github.com/users/simonmar/repos","events_url":"https://api.github.com/users/simonmar/events{/privacy}","received_events_url":"https://api.github.com/users/simonmar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/simonmar/alex","description":"A lexical analyser generator for Haskell","fork":false,"url":"https://api.github.com/repos/simonmar/alex","forks_url":"https://api.github.com/repos/simonmar/alex/forks","keys_url":"https://api.github.com/repos/simonmar/alex/keys{/key_id}","collaborators_url":"https://api.github.com/repos/simonmar/alex/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/simonmar/alex/teams","hooks_url":"https://api.github.com/repos/simonmar/alex/hooks","issue_events_url":"https://api.github.com/repos/simonmar/alex/issues/events{/number}","events_url":"https://api.github.com/repos/simonmar/alex/events","assignees_url":"https://api.github.com/repos/simonmar/alex/assignees{/user}","branches_url":"https://api.github.com/repos/simonmar/alex/branches{/branch}","tags_url":"https://api.github.com/repos/simonmar/alex/tags","blobs_url":"https://api.github.com/repos/simonmar/alex/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/simonmar/alex/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/simonmar/alex/git/refs{/sha}","trees_url":"https://api.github.com/repos/simonmar/alex/git/trees{/sha}","statuses_url":"https://api.github.com/repos/simonmar/alex/statuses/{sha}","languages_url":"https://api.github.com/repos/simonmar/alex/languages","stargazers_url":"https://api.github.com/repos/simonmar/alex/stargazers","contributors_url":"https://api.github.com/repos/simonmar/alex/contributors","subscribers_url":"https://api.github.com/repos/simonmar/alex/subscribers","subscription_url":"https://api.github.com/repos/simonmar/alex/subscription","commits_url":"https://api.github.com/repos/simonmar/alex/commits{/sha}","git_commits_url":"https://api.github.com/repos/simonmar/alex/git/commits{/sha}","comments_url":"https://api.github.com/repos/simonmar/alex/comments{/number}","issue_comment_url":"https://api.github.com/repos/simonmar/alex/issues/comments{/number}","contents_url":"https://api.github.com/repos/simonmar/alex/contents/{+path}","compare_url":"https://api.github.com/repos/simonmar/alex/compare/{base}...{head}","merges_url":"https://api.github.com/repos/simonmar/alex/merges","archive_url":"https://api.github.com/repos/simonmar/alex/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/simonmar/alex/downloads","issues_url":"https://api.github.com/repos/simonmar/alex/issues{/number}","pulls_url":"https://api.github.com/repos/simonmar/alex/pulls{/number}","milestones_url":"https://api.github.com/repos/simonmar/alex/milestones{/number}","notifications_url":"https://api.github.com/repos/simonmar/alex/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/simonmar/alex/labels{/name}","releases_url":"https://api.github.com/repos/simonmar/alex/releases{/id}","deployments_url":"https://api.github.com/repos/simonmar/alex/deployments","created_at":"2011-07-11T20:13:56Z","updated_at":"2016-01-15T16:24:10Z","pushed_at":"2016-02-02T16:20:00Z","git_url":"git://github.com/simonmar/alex.git","ssh_url":"git@github.com:simonmar/alex.git","clone_url":"https://github.com/simonmar/alex.git","svn_url":"https://github.com/simonmar/alex","homepage":"http://www.haskell.org/alex","size":698,"stargazers_count":67,"watchers_count":67,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":40,"mirror_url":null,"open_issues_count":15,"forks":40,"open_issues":15,"watchers":67,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/simonmar/alex/pulls/68"},"html":{"href":"https://github.com/simonmar/alex/pull/68"},"issue":{"href":"https://api.github.com/repos/simonmar/alex/issues/68"},"comments":{"href":"https://api.github.com/repos/simonmar/alex/issues/68/comments"},"review_comments":{"href":"https://api.github.com/repos/simonmar/alex/pulls/68/comments"},"review_comment":{"href":"https://api.github.com/repos/simonmar/alex/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/simonmar/alex/pulls/68/commits"},"statuses":{"href":"https://api.github.com/repos/simonmar/alex/statuses/d9e530640561ecedded8ad000f18e9ae793a468f"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"simonmar","id":609606,"avatar_url":"https://avatars.githubusercontent.com/u/609606?v=3","gravatar_id":"","url":"https://api.github.com/users/simonmar","html_url":"https://github.com/simonmar","followers_url":"https://api.github.com/users/simonmar/followers","following_url":"https://api.github.com/users/simonmar/following{/other_user}","gists_url":"https://api.github.com/users/simonmar/gists{/gist_id}","starred_url":"https://api.github.com/users/simonmar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/simonmar/subscriptions","organizations_url":"https://api.github.com/users/simonmar/orgs","repos_url":"https://api.github.com/users/simonmar/repos","events_url":"https://api.github.com/users/simonmar/events{/privacy}","received_events_url":"https://api.github.com/users/simonmar/received_events","type":"User","site_admin":false},"comments":9,"review_comments":0,"commits":16,"additions":1892,"deletions":154,"changed_files":20}}