payload: {"action":"created","comment":{"url":"https://api.github.com/repos/isovector/polysemy/pulls/comments/279863234","pull_request_review_id":232310082,"id":279863234,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI3OTg2MzIzNA==","diff_hunk":"@@ -61,39 +61,136 @@ Make sure you read the [Necessary Language\n Extensions](https://github.com/isovector/polysemy#necessary-language-extensions)\n before trying these yourself!\n \n-Console effect:\n+Teletype effect:\n \n ```haskell\n {-# LANGUAGE TemplateHaskell #-}\n+{-# LANGUAGE BlockArguments, DataKinds, FlexibleContexts, GADTs, LambdaCase,\n+             PolyKinds, RankNTypes, ScopedTypeVariables, TypeApplications,\n+             TypeOperators, TypeFamilies, UnicodeSyntax\n+#-}\n \n import Polysemy\n+import Polysemy.Input\n+import Polysemy.Output\n \n-data Console m a where\n-  ReadTTY  :: Console m String\n-  WriteTTY :: String -> Console m ()\n+data Teletype m a where\n+  ReadTTY  :: Teletype m String\n+  WriteTTY :: String -> Teletype m ()\n \n-makeSem ''Console\n+makeSem ''Teletype\n \n-runConsoleIO :: Member (Lift IO) r => Sem (Console ': r) a -> Sem r a\n-runConsoleIO = interpret $ \\case\n+runTeletypeIO :: Member (Lift IO) r => Sem (Teletype ': r) a -> Sem r a\n+runTeletypeIO = interpret $ \\case\n   ReadTTY      -> sendM getLine\n   WriteTTY msg -> sendM $ putStrLn msg\n+\n+runTeletypeBoring :: [String] -> Sem (Teletype ': r) a -> Sem r ([String], a)\n+runTeletypeBoring i\n+  = runFoldMapOutput pure\n+  . runListInput i\n+  . reinterpret2 \\case\n+      ReadTTY -> maybe \"\" id <$> input\n+      WriteTTY msg -> output msg\n+\n+-- Continuations so we can build up chains of behavior\n+echoK :: Member Teletype r => Sem r () -> Sem r ()\n+echoK k = do\n+  a <- readTTY\n+  when (a == \"\") $ pure ()\n+  when (a /= \"\") do\n+    writeTTY a\n+    k\n+\n+revK :: Member Teletype r => Sem r () -> Sem r ()\n+revK k = do\n+  a <- readTTY\n+  when (a == \"\") $ pure ()\n+  when (a /= \"\") do\n+    writeTTY (reverse a)\n+    k\n+\n+-- Fixpoints\n+\n+echo :: Member Teletype r => Sem r ()\n+echo = fix echoK\n+\n+rev :: Member Teletype r => Sem r ()\n+rev = fix revK\n+\n+alternating :: Member Teletype r => Sem r ()\n+alternating = fix (echoK . revK)\n+\n+-- Let's pretend\n+echoBoring :: [String] -> Sem '[] ([String], ())\n+echoBoring = flip runTeletypeBoring echo\n+\n+revBoring :: [String] -> Sem '[] ([String], ())\n+revBoring = flip runTeletypeBoring rev\n+\n+alternatingBoring :: [String] -> Sem '[] ([String], ())\n+alternatingBoring = flip runTeletypeBoring alternating\n+\n+boring :: [String] -> [[String]]\n+boring = map (fst . run) . sequence [echoBoring, revBoring, alternatingBoring]\n+\n+-- Now let's do things\n+echoIO :: Sem '[Lift IO] ()\n+echoIO = runTeletypeIO echo\n+\n+revIO :: Sem '[Lift IO] ()\n+revIO = runTeletypeIO rev\n+\n+alternatingIO :: Sem '[Lift IO] ()\n+alternatingIO = runTeletypeIO alternating\n+\n+-- cycle echo and reverse until a blank line\n+main :: IO ()\n+main = runM alternatingIO\n ```\n \n \n Resource effect:\n \n ```haskell\n {-# LANGUAGE TemplateHaskell #-}\n+{-# LANGUAGE BlockArguments, DataKinds, FlexibleContexts, GADTs, LambdaCase,\n+             PolyKinds, RankNTypes, ScopedTypeVariables, TypeApplications,\n+             TypeOperators, TypeFamilies, UnicodeSyntax\n+#-}\n \n+import Prelude hiding (throw, catch, bracket)\n+import Polysemy\n+import Polysemy.Input\n+import Polysemy.Output\n+import Polysemy.Error\n import qualified Control.Exception as X\n-import           Polysemy\n+\n+data Teletype m a where\n+  ReadTTY  :: Teletype m String\n+  WriteTTY :: String -> Teletype m ()\n \n data Resource m a where\n   Bracket :: m a -> (a -> m ()) -> (a -> m b) -> Resource m b\n \n+makeSem ''Teletype\n makeSem ''Resource\n \n+\n+runTeletypeIO :: Member (Lift IO) r => Sem (Teletype ': r) a -> Sem r a\n+runTeletypeIO = interpret $ \\case\n+  ReadTTY      -> sendM getLine\n+  WriteTTY msg -> sendM $ putStrLn msg\n+\n+runTeletypeBoring :: [String] -> Sem (Teletype ': r) a -> Sem r ([String], a)\n+runTeletypeBoring i\n+  = runFoldMapOutput pure\n+  . runListInput i\n+  . reinterpret2 \\case","path":"README.md","position":137,"original_position":137,"commit_id":"1024edeaf3458df67d9ded335d12ef841b7387f0","original_commit_id":"1024edeaf3458df67d9ded335d12ef841b7387f0","user":{"login":"isovector","id":307223,"node_id":"MDQ6VXNlcjMwNzIyMw==","avatar_url":"https://avatars3.githubusercontent.com/u/307223?v=4","gravatar_id":"","url":"https://api.github.com/users/isovector","html_url":"https://github.com/isovector","followers_url":"https://api.github.com/users/isovector/followers","following_url":"https://api.github.com/users/isovector/following{/other_user}","gists_url":"https://api.github.com/users/isovector/gists{/gist_id}","starred_url":"https://api.github.com/users/isovector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isovector/subscriptions","organizations_url":"https://api.github.com/users/isovector/orgs","repos_url":"https://api.github.com/users/isovector/repos","events_url":"https://api.github.com/users/isovector/events{/privacy}","received_events_url":"https://api.github.com/users/isovector/received_events","type":"User","site_admin":false},"body":"I really like this, but a comment or two would probably go a long way.","created_at":"2019-04-30T17:45:05Z","updated_at":"2019-04-30T17:45:55Z","html_url":"https://github.com/isovector/polysemy/pull/12#discussion_r279863234","pull_request_url":"https://api.github.com/repos/isovector/polysemy/pulls/12","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/comments/279863234"},"html":{"href":"https://github.com/isovector/polysemy/pull/12#discussion_r279863234"},"pull_request":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/isovector/polysemy/pulls/12","id":270097495,"node_id":"MDExOlB1bGxSZXF1ZXN0MjcwMDk3NDk1","html_url":"https://github.com/isovector/polysemy/pull/12","diff_url":"https://github.com/isovector/polysemy/pull/12.diff","patch_url":"https://github.com/isovector/polysemy/pull/12.patch","issue_url":"https://api.github.com/repos/isovector/polysemy/issues/12","number":12,"state":"open","locked":false,"title":"Extend examples, make them easy to copy and paste","user":{"login":"jhenahan","id":863367,"node_id":"MDQ6VXNlcjg2MzM2Nw==","avatar_url":"https://avatars2.githubusercontent.com/u/863367?v=4","gravatar_id":"","url":"https://api.github.com/users/jhenahan","html_url":"https://github.com/jhenahan","followers_url":"https://api.github.com/users/jhenahan/followers","following_url":"https://api.github.com/users/jhenahan/following{/other_user}","gists_url":"https://api.github.com/users/jhenahan/gists{/gist_id}","starred_url":"https://api.github.com/users/jhenahan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhenahan/subscriptions","organizations_url":"https://api.github.com/users/jhenahan/orgs","repos_url":"https://api.github.com/users/jhenahan/repos","events_url":"https://api.github.com/users/jhenahan/events{/privacy}","received_events_url":"https://api.github.com/users/jhenahan/received_events","type":"User","site_admin":false},"body":"For the purpose of getting new users off on the right foot immediately, I added the necessary pragmas to get these working, and built out a trivial example of how to actually use `runConsoleIO`. I wanted to write something like `runConsoleBoring` as an example of mocking using `Input` and `Output` maybe(?), but I wasn't sure how to go about it. I also haven't tried writing a `Resource` example, yet.","created_at":"2019-04-12T17:45:01Z","updated_at":"2019-04-30T17:45:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"32ae065e7ca16789db62628e536f5aed13898479","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/isovector/polysemy/pulls/12/commits","review_comments_url":"https://api.github.com/repos/isovector/polysemy/pulls/12/comments","review_comment_url":"https://api.github.com/repos/isovector/polysemy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/isovector/polysemy/issues/12/comments","statuses_url":"https://api.github.com/repos/isovector/polysemy/statuses/1024edeaf3458df67d9ded335d12ef841b7387f0","head":{"label":"jhenahan:patch-1","ref":"patch-1","sha":"1024edeaf3458df67d9ded335d12ef841b7387f0","user":{"login":"jhenahan","id":863367,"node_id":"MDQ6VXNlcjg2MzM2Nw==","avatar_url":"https://avatars2.githubusercontent.com/u/863367?v=4","gravatar_id":"","url":"https://api.github.com/users/jhenahan","html_url":"https://github.com/jhenahan","followers_url":"https://api.github.com/users/jhenahan/followers","following_url":"https://api.github.com/users/jhenahan/following{/other_user}","gists_url":"https://api.github.com/users/jhenahan/gists{/gist_id}","starred_url":"https://api.github.com/users/jhenahan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhenahan/subscriptions","organizations_url":"https://api.github.com/users/jhenahan/orgs","repos_url":"https://api.github.com/users/jhenahan/repos","events_url":"https://api.github.com/users/jhenahan/events{/privacy}","received_events_url":"https://api.github.com/users/jhenahan/received_events","type":"User","site_admin":false},"repo":{"id":181050538,"node_id":"MDEwOlJlcG9zaXRvcnkxODEwNTA1Mzg=","name":"polysemy","full_name":"jhenahan/polysemy","private":false,"owner":{"login":"jhenahan","id":863367,"node_id":"MDQ6VXNlcjg2MzM2Nw==","avatar_url":"https://avatars2.githubusercontent.com/u/863367?v=4","gravatar_id":"","url":"https://api.github.com/users/jhenahan","html_url":"https://github.com/jhenahan","followers_url":"https://api.github.com/users/jhenahan/followers","following_url":"https://api.github.com/users/jhenahan/following{/other_user}","gists_url":"https://api.github.com/users/jhenahan/gists{/gist_id}","starred_url":"https://api.github.com/users/jhenahan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhenahan/subscriptions","organizations_url":"https://api.github.com/users/jhenahan/orgs","repos_url":"https://api.github.com/users/jhenahan/repos","events_url":"https://api.github.com/users/jhenahan/events{/privacy}","received_events_url":"https://api.github.com/users/jhenahan/received_events","type":"User","site_admin":false},"html_url":"https://github.com/jhenahan/polysemy","description":"higher-order, no-boilerplate, zero-cost monads","fork":true,"url":"https://api.github.com/repos/jhenahan/polysemy","forks_url":"https://api.github.com/repos/jhenahan/polysemy/forks","keys_url":"https://api.github.com/repos/jhenahan/polysemy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jhenahan/polysemy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jhenahan/polysemy/teams","hooks_url":"https://api.github.com/repos/jhenahan/polysemy/hooks","issue_events_url":"https://api.github.com/repos/jhenahan/polysemy/issues/events{/number}","events_url":"https://api.github.com/repos/jhenahan/polysemy/events","assignees_url":"https://api.github.com/repos/jhenahan/polysemy/assignees{/user}","branches_url":"https://api.github.com/repos/jhenahan/polysemy/branches{/branch}","tags_url":"https://api.github.com/repos/jhenahan/polysemy/tags","blobs_url":"https://api.github.com/repos/jhenahan/polysemy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jhenahan/polysemy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jhenahan/polysemy/git/refs{/sha}","trees_url":"https://api.github.com/repos/jhenahan/polysemy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jhenahan/polysemy/statuses/{sha}","languages_url":"https://api.github.com/repos/jhenahan/polysemy/languages","stargazers_url":"https://api.github.com/repos/jhenahan/polysemy/stargazers","contributors_url":"https://api.github.com/repos/jhenahan/polysemy/contributors","subscribers_url":"https://api.github.com/repos/jhenahan/polysemy/subscribers","subscription_url":"https://api.github.com/repos/jhenahan/polysemy/subscription","commits_url":"https://api.github.com/repos/jhenahan/polysemy/commits{/sha}","git_commits_url":"https://api.github.com/repos/jhenahan/polysemy/git/commits{/sha}","comments_url":"https://api.github.com/repos/jhenahan/polysemy/comments{/number}","issue_comment_url":"https://api.github.com/repos/jhenahan/polysemy/issues/comments{/number}","contents_url":"https://api.github.com/repos/jhenahan/polysemy/contents/{+path}","compare_url":"https://api.github.com/repos/jhenahan/polysemy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jhenahan/polysemy/merges","archive_url":"https://api.github.com/repos/jhenahan/polysemy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jhenahan/polysemy/downloads","issues_url":"https://api.github.com/repos/jhenahan/polysemy/issues{/number}","pulls_url":"https://api.github.com/repos/jhenahan/polysemy/pulls{/number}","milestones_url":"https://api.github.com/repos/jhenahan/polysemy/milestones{/number}","notifications_url":"https://api.github.com/repos/jhenahan/polysemy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jhenahan/polysemy/labels{/name}","releases_url":"https://api.github.com/repos/jhenahan/polysemy/releases{/id}","deployments_url":"https://api.github.com/repos/jhenahan/polysemy/deployments","created_at":"2019-04-12T17:05:28Z","updated_at":"2019-04-12T17:05:30Z","pushed_at":"2019-04-30T17:17:57Z","git_url":"git://github.com/jhenahan/polysemy.git","ssh_url":"git@github.com:jhenahan/polysemy.git","clone_url":"https://github.com/jhenahan/polysemy.git","svn_url":"https://github.com/jhenahan/polysemy","homepage":"","size":278,"stargazers_count":0,"watchers_count":0,"language":"Haskell","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"isovector:master","ref":"master","sha":"6dd61d66103436ebe5db418a2daba2912ffaca70","user":{"login":"isovector","id":307223,"node_id":"MDQ6VXNlcjMwNzIyMw==","avatar_url":"https://avatars3.githubusercontent.com/u/307223?v=4","gravatar_id":"","url":"https://api.github.com/users/isovector","html_url":"https://github.com/isovector","followers_url":"https://api.github.com/users/isovector/followers","following_url":"https://api.github.com/users/isovector/following{/other_user}","gists_url":"https://api.github.com/users/isovector/gists{/gist_id}","starred_url":"https://api.github.com/users/isovector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isovector/subscriptions","organizations_url":"https://api.github.com/users/isovector/orgs","repos_url":"https://api.github.com/users/isovector/repos","events_url":"https://api.github.com/users/isovector/events{/privacy}","received_events_url":"https://api.github.com/users/isovector/received_events","type":"User","site_admin":false},"repo":{"id":170577949,"node_id":"MDEwOlJlcG9zaXRvcnkxNzA1Nzc5NDk=","name":"polysemy","full_name":"isovector/polysemy","private":false,"owner":{"login":"isovector","id":307223,"node_id":"MDQ6VXNlcjMwNzIyMw==","avatar_url":"https://avatars3.githubusercontent.com/u/307223?v=4","gravatar_id":"","url":"https://api.github.com/users/isovector","html_url":"https://github.com/isovector","followers_url":"https://api.github.com/users/isovector/followers","following_url":"https://api.github.com/users/isovector/following{/other_user}","gists_url":"https://api.github.com/users/isovector/gists{/gist_id}","starred_url":"https://api.github.com/users/isovector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isovector/subscriptions","organizations_url":"https://api.github.com/users/isovector/orgs","repos_url":"https://api.github.com/users/isovector/repos","events_url":"https://api.github.com/users/isovector/events{/privacy}","received_events_url":"https://api.github.com/users/isovector/received_events","type":"User","site_admin":false},"html_url":"https://github.com/isovector/polysemy","description":":gemini: higher-order, no-boilerplate, zero-cost monads","fork":false,"url":"https://api.github.com/repos/isovector/polysemy","forks_url":"https://api.github.com/repos/isovector/polysemy/forks","keys_url":"https://api.github.com/repos/isovector/polysemy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/isovector/polysemy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/isovector/polysemy/teams","hooks_url":"https://api.github.com/repos/isovector/polysemy/hooks","issue_events_url":"https://api.github.com/repos/isovector/polysemy/issues/events{/number}","events_url":"https://api.github.com/repos/isovector/polysemy/events","assignees_url":"https://api.github.com/repos/isovector/polysemy/assignees{/user}","branches_url":"https://api.github.com/repos/isovector/polysemy/branches{/branch}","tags_url":"https://api.github.com/repos/isovector/polysemy/tags","blobs_url":"https://api.github.com/repos/isovector/polysemy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/isovector/polysemy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/isovector/polysemy/git/refs{/sha}","trees_url":"https://api.github.com/repos/isovector/polysemy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/isovector/polysemy/statuses/{sha}","languages_url":"https://api.github.com/repos/isovector/polysemy/languages","stargazers_url":"https://api.github.com/repos/isovector/polysemy/stargazers","contributors_url":"https://api.github.com/repos/isovector/polysemy/contributors","subscribers_url":"https://api.github.com/repos/isovector/polysemy/subscribers","subscription_url":"https://api.github.com/repos/isovector/polysemy/subscription","commits_url":"https://api.github.com/repos/isovector/polysemy/commits{/sha}","git_commits_url":"https://api.github.com/repos/isovector/polysemy/git/commits{/sha}","comments_url":"https://api.github.com/repos/isovector/polysemy/comments{/number}","issue_comment_url":"https://api.github.com/repos/isovector/polysemy/issues/comments{/number}","contents_url":"https://api.github.com/repos/isovector/polysemy/contents/{+path}","compare_url":"https://api.github.com/repos/isovector/polysemy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/isovector/polysemy/merges","archive_url":"https://api.github.com/repos/isovector/polysemy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/isovector/polysemy/downloads","issues_url":"https://api.github.com/repos/isovector/polysemy/issues{/number}","pulls_url":"https://api.github.com/repos/isovector/polysemy/pulls{/number}","milestones_url":"https://api.github.com/repos/isovector/polysemy/milestones{/number}","notifications_url":"https://api.github.com/repos/isovector/polysemy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/isovector/polysemy/labels{/name}","releases_url":"https://api.github.com/repos/isovector/polysemy/releases{/id}","deployments_url":"https://api.github.com/repos/isovector/polysemy/deployments","created_at":"2019-02-13T20:53:25Z","updated_at":"2019-04-30T17:25:54Z","pushed_at":"2019-04-30T17:25:52Z","git_url":"git://github.com/isovector/polysemy.git","ssh_url":"git@github.com:isovector/polysemy.git","clone_url":"https://github.com/isovector/polysemy.git","svn_url":"https://github.com/isovector/polysemy","homepage":"","size":274,"stargazers_count":250,"watchers_count":250,"language":"Haskell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":13,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":8,"open_issues":13,"watchers":250,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/12"},"html":{"href":"https://github.com/isovector/polysemy/pull/12"},"issue":{"href":"https://api.github.com/repos/isovector/polysemy/issues/12"},"comments":{"href":"https://api.github.com/repos/isovector/polysemy/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/isovector/polysemy/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/isovector/polysemy/statuses/1024edeaf3458df67d9ded335d12ef841b7387f0"}},"author_association":"NONE"}}
other: {"actor":{"display_login":"isovector"}}