{"action":"created","comment":{"url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/comments/26548348","id":26548348,"diff_hunk":"@@ -0,0 +1,898 @@\n+第七章：I/O\n+===========\n+\n+很明显就算不是所有，绝大多数的程序员致力于从外部收集数据，处理这些数据，然后把结果传回外部世界。也就是说，输入输出是关键的。\n+\n+Haskell的I/O系统是很强大和富有表现力的。它很容易使用，而且去你要去理解它，这很重要。Haskell严格地把Pure代码从那些会让外部世界发生事情的代码中分隔开。就是说，它给Pure代码提供了完全的副作用隔离。除了帮助程序员推断他们自己代码的正确性，它还使编译器可以自动采取优化和并行化成为可能。\n+\n+我们将用简单标准的I/O来开始这一章。然后我们要讨论下一些更强大的选项，以及提供更多I/O是怎么适应存的，惰性的，函数式的Haskell世界的细节。\n+\n+Haskell经典I/O\n+--------------\n+\n+让我们开始Haskell的I/O，先来看一个程序，它看起来很像在C或者Perl等其他语言的I/O。\n+\n+::\n+\n+    -- file: ch07/basicio.hs\n+    main = do\n+        putStrLn \"Greetings!  What is your name?\"\n+        inpStr <- getLine\n+        putStrLn $ \"Welcome to Haskell, \" ++ inpStr ++ \"!\"\n+\n+你可以编译这个程序，变成一个单独的可执行文件，然后用**runghc**运行它，或者从**ghci**调用 ``main`` 。这里有一个使用**runghc**的例子：\n+\n+::\n+\n+   $ runghc basicio.hs\n+   Greetings!  What is your name?\n+   John\n+   Welcome to Haskell, John!\n+\n+这相单简单，结果很明显。你可以看到 ``putStrLn`` 输出一个 ``string`` ，后面跟了一个换行符。 ``getLine`` 从标准输入读取一行。 ``<-`` 语法对于你可能比较新。简单来看，它绑定一个I/O操作的结果到一个名字。我们用简单的列表串联操作符 ``++`` 来联合输入字符串和我们自己的文本。\n+\n+让我们来看一下 ``putStrLn`` 和 ``getLine`` 的类型。你可以在库参考手册里看到这些信息，或者直接问 ``ghci`` ：\n+\n+::\n+\n+   ghci> :type putStrLn\n+   putStrLn :: String -> IO ()\n+   ghci> :type getLine\n+   getLine :: IO String\n+\n+注意，这些类型在他们的返回值里面都有IO。现在关键的是，你要从这里知道他们可能有副作用，或者他们用相同的参数调用可能返回不同的值，或者两者都有。 ``putStrLn`` 的类型看起来像一个函数，它接受一个 ``String`` 类型的参数，并返回 ``IO ()`` 类型的值。可是 ``IO ()`` 是什么呢？\n+\n+``IO something`` 类型的所有东西都是一个IO操作，你可以保存它但是什么都不会发生。我可以说 ``writefoo = putStrLn \"foo\"`` 并且现在什么都不发生。但是如果我过一会在另一个I/O操作中间使用 ``writefoo`` ， ``writefoo`` 操作将会在它的父操作被执行的时候执行 -- I/O操作可以粘合在一起来形成更大的I/O操作。 ``()`` 是一个空的元组（读作“unit”），表明从 ``putStrLn`` 没有返回值。这和Java或C里面的 ``void`` 类似。\n+\n+.. tip::\n+   I/O操作可以被创建，赋值和传递到任何地方，但是它们只能呢个在另一个I/O操作里面被执行。\n+\n+我们在 **ghci** 下看下这句代码：\n+\n+::\n+\n+   ghci> let writefoo = putStrLn \"foo\"\n+   ghci> writefoo\n+   foo\n+\n+在这个例子中，输出 ``foo`` 不是 ``putStrLn`` 的返回值，而是它的副作用，把 ``foo`` 写到终端上。\n+\n+还有另一件事要注意， 实际上是 **ghci** 执行的 ``writefoo`` 。意思是，如果给 **ghci** 一个I/O操作，它将会在那个地方帮你执行它。\n+\n+.. note::\n+   什么是I/O操作？\n+   * 类型是 ``IO t``\n+   * 是Haskell的头等值，并且和Haskell的类型系统无缝结合。\n+   * 在运行（perform）的时候产生作用，而不是在估值（evaluate）的时候。\n+   * 任何表达式都会产生一个操作作为它的值，但是这个操作直到在另一个I/O操作里面被执行的时候才会运行。\n+   * 运行（执行）一个 ``IO t`` 类型的操作可能运行I/O，并且最终交付一个类型 ``t`` 的结果。\n+\n+\n+``getLine`` 的类型可能看起来比较陌生。它看起来像一个值，而不像一个函数。但实际上，有一种看它的方法： ``getLine`` 保存了一个I/O操作。当这个操作运行了你会得到一个 ``String`` 。 ``<-`` 操作符是用来从运行I/O操作中抽出结果，并且保存到一个变量中。\n+\n+``main`` 自己就是一个I/O操作，类型是 ``IO ()`` 。你可以在其他I/O操作中只是运行I/O操作。Haskell程序中的所有I/O操作都是由从 ``main`` 的顶部开始驱动的， ``main`` 是每一个Haskell程序开始执行的地方。然后，要说的是给Haskell中副作用提供隔离的机制是：你在I/O操作中运行I/O，并且在那儿调用存的（非I/O）函数。大部分Haskell代码是存的，I/O操作运行I/O并且调用存代码。\n+\n+``do`` 是用来定义一串操作的方便方法。你马上就会看到，还有其他方法可以用来定义。当你用这种方式来使用 ``do`` 的时候，缩进很重要，确保你的操作正确地对齐了。\n+\n+只有当你有多余一个操作需要运行的时候才要用到 ``do`` 。 ``do`` 代码块的值是最后一个操作执行的结果。想要看 ``do`` 语法的完整介绍，可以看 `do代码块提取`_ .\n+\n+我们来考虑一个在I/O操作中调用存代码的一个例子：","path":"chp/7.rst","position":79,"original_position":79,"commit_id":"ae943c17234734621cd80e4c040ad3a449c1359b","original_commit_id":"d75c47a83451b00573b1c74529a422be79c1cd23","user":{"login":"huangz1990","id":536854,"avatar_url":"https://avatars.githubusercontent.com/u/536854?v=3","gravatar_id":"","url":"https://api.github.com/users/huangz1990","html_url":"https://github.com/huangz1990","followers_url":"https://api.github.com/users/huangz1990/followers","following_url":"https://api.github.com/users/huangz1990/following{/other_user}","gists_url":"https://api.github.com/users/huangz1990/gists{/gist_id}","starred_url":"https://api.github.com/users/huangz1990/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huangz1990/subscriptions","organizations_url":"https://api.github.com/users/huangz1990/orgs","repos_url":"https://api.github.com/users/huangz1990/repos","events_url":"https://api.github.com/users/huangz1990/events{/privacy}","received_events_url":"https://api.github.com/users/huangz1990/received_events","type":"User","site_admin":false},"body":"这个句子之后应该有空行，这样 ``::`` 才能正确地格式化。","created_at":"2015-03-17T04:13:18Z","updated_at":"2015-03-17T04:13:18Z","html_url":"https://github.com/huangz1990/real-world-haskell-cn/pull/21#discussion_r26548348","pull_request_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21","_links":{"self":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/comments/26548348"},"html":{"href":"https://github.com/huangz1990/real-world-haskell-cn/pull/21#discussion_r26548348"},"pull_request":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21"}}},"pull_request":{"url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21","id":31207778,"html_url":"https://github.com/huangz1990/real-world-haskell-cn/pull/21","diff_url":"https://github.com/huangz1990/real-world-haskell-cn/pull/21.diff","patch_url":"https://github.com/huangz1990/real-world-haskell-cn/pull/21.patch","issue_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/21","number":21,"state":"open","locked":false,"title":"第七章的翻译","user":{"login":"yanguango","id":63400,"avatar_url":"https://avatars.githubusercontent.com/u/63400?v=3","gravatar_id":"","url":"https://api.github.com/users/yanguango","html_url":"https://github.com/yanguango","followers_url":"https://api.github.com/users/yanguango/followers","following_url":"https://api.github.com/users/yanguango/following{/other_user}","gists_url":"https://api.github.com/users/yanguango/gists{/gist_id}","starred_url":"https://api.github.com/users/yanguango/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yanguango/subscriptions","organizations_url":"https://api.github.com/users/yanguango/orgs","repos_url":"https://api.github.com/users/yanguango/repos","events_url":"https://api.github.com/users/yanguango/events{/privacy}","received_events_url":"https://api.github.com/users/yanguango/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-03-15T21:35:14Z","updated_at":"2015-03-17T04:13:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"98ed95cac5e60d576efd724811f551772ce1ad35","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21/commits","review_comments_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21/comments","review_comment_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/comments{/number}","comments_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/21/comments","statuses_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/statuses/ae943c17234734621cd80e4c040ad3a449c1359b","head":{"label":"yanguango:master","ref":"master","sha":"ae943c17234734621cd80e4c040ad3a449c1359b","user":{"login":"yanguango","id":63400,"avatar_url":"https://avatars.githubusercontent.com/u/63400?v=3","gravatar_id":"","url":"https://api.github.com/users/yanguango","html_url":"https://github.com/yanguango","followers_url":"https://api.github.com/users/yanguango/followers","following_url":"https://api.github.com/users/yanguango/following{/other_user}","gists_url":"https://api.github.com/users/yanguango/gists{/gist_id}","starred_url":"https://api.github.com/users/yanguango/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yanguango/subscriptions","organizations_url":"https://api.github.com/users/yanguango/orgs","repos_url":"https://api.github.com/users/yanguango/repos","events_url":"https://api.github.com/users/yanguango/events{/privacy}","received_events_url":"https://api.github.com/users/yanguango/received_events","type":"User","site_admin":false},"repo":{"id":31639513,"name":"real-world-haskell-cn","full_name":"yanguango/real-world-haskell-cn","owner":{"login":"yanguango","id":63400,"avatar_url":"https://avatars.githubusercontent.com/u/63400?v=3","gravatar_id":"","url":"https://api.github.com/users/yanguango","html_url":"https://github.com/yanguango","followers_url":"https://api.github.com/users/yanguango/followers","following_url":"https://api.github.com/users/yanguango/following{/other_user}","gists_url":"https://api.github.com/users/yanguango/gists{/gist_id}","starred_url":"https://api.github.com/users/yanguango/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yanguango/subscriptions","organizations_url":"https://api.github.com/users/yanguango/orgs","repos_url":"https://api.github.com/users/yanguango/repos","events_url":"https://api.github.com/users/yanguango/events{/privacy}","received_events_url":"https://api.github.com/users/yanguango/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/yanguango/real-world-haskell-cn","description":"Real World Haskell 的中文翻译","fork":true,"url":"https://api.github.com/repos/yanguango/real-world-haskell-cn","forks_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/forks","keys_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/teams","hooks_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/hooks","issue_events_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/issues/events{/number}","events_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/events","assignees_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/assignees{/user}","branches_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/branches{/branch}","tags_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/tags","blobs_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/git/refs{/sha}","trees_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/statuses/{sha}","languages_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/languages","stargazers_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/stargazers","contributors_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/contributors","subscribers_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/subscribers","subscription_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/subscription","commits_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/commits{/sha}","git_commits_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/git/commits{/sha}","comments_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/comments{/number}","issue_comment_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/issues/comments{/number}","contents_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/contents/{+path}","compare_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/merges","archive_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/downloads","issues_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/issues{/number}","pulls_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/pulls{/number}","milestones_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/milestones{/number}","notifications_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/labels{/name}","releases_url":"https://api.github.com/repos/yanguango/real-world-haskell-cn/releases{/id}","created_at":"2015-03-04T05:21:35Z","updated_at":"2015-03-17T03:51:28Z","pushed_at":"2015-03-17T03:51:27Z","git_url":"git://github.com/yanguango/real-world-haskell-cn.git","ssh_url":"git@github.com:yanguango/real-world-haskell-cn.git","clone_url":"https://github.com/yanguango/real-world-haskell-cn.git","svn_url":"https://github.com/yanguango/real-world-haskell-cn","homepage":"http://rwh.readthedocs.org/","size":775,"stargazers_count":0,"watchers_count":0,"language":"Haskell","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"huangz1990:master","ref":"master","sha":"4f59656f5d62b4ef579cb87a7e0a0b36ecea6c0a","user":{"login":"huangz1990","id":536854,"avatar_url":"https://avatars.githubusercontent.com/u/536854?v=3","gravatar_id":"","url":"https://api.github.com/users/huangz1990","html_url":"https://github.com/huangz1990","followers_url":"https://api.github.com/users/huangz1990/followers","following_url":"https://api.github.com/users/huangz1990/following{/other_user}","gists_url":"https://api.github.com/users/huangz1990/gists{/gist_id}","starred_url":"https://api.github.com/users/huangz1990/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huangz1990/subscriptions","organizations_url":"https://api.github.com/users/huangz1990/orgs","repos_url":"https://api.github.com/users/huangz1990/repos","events_url":"https://api.github.com/users/huangz1990/events{/privacy}","received_events_url":"https://api.github.com/users/huangz1990/received_events","type":"User","site_admin":false},"repo":{"id":6297752,"name":"real-world-haskell-cn","full_name":"huangz1990/real-world-haskell-cn","owner":{"login":"huangz1990","id":536854,"avatar_url":"https://avatars.githubusercontent.com/u/536854?v=3","gravatar_id":"","url":"https://api.github.com/users/huangz1990","html_url":"https://github.com/huangz1990","followers_url":"https://api.github.com/users/huangz1990/followers","following_url":"https://api.github.com/users/huangz1990/following{/other_user}","gists_url":"https://api.github.com/users/huangz1990/gists{/gist_id}","starred_url":"https://api.github.com/users/huangz1990/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huangz1990/subscriptions","organizations_url":"https://api.github.com/users/huangz1990/orgs","repos_url":"https://api.github.com/users/huangz1990/repos","events_url":"https://api.github.com/users/huangz1990/events{/privacy}","received_events_url":"https://api.github.com/users/huangz1990/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/huangz1990/real-world-haskell-cn","description":"Real World Haskell 的中文翻译","fork":false,"url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn","forks_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/forks","keys_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/teams","hooks_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/hooks","issue_events_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/events{/number}","events_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/events","assignees_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/assignees{/user}","branches_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/branches{/branch}","tags_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/tags","blobs_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/git/refs{/sha}","trees_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/statuses/{sha}","languages_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/languages","stargazers_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/stargazers","contributors_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/contributors","subscribers_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/subscribers","subscription_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/subscription","commits_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/commits{/sha}","git_commits_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/git/commits{/sha}","comments_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/comments{/number}","issue_comment_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/comments{/number}","contents_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/contents/{+path}","compare_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/merges","archive_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/downloads","issues_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues{/number}","pulls_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls{/number}","milestones_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/milestones{/number}","notifications_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/labels{/name}","releases_url":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/releases{/id}","created_at":"2012-10-19T16:07:47Z","updated_at":"2015-03-12T05:57:27Z","pushed_at":"2015-03-12T05:20:54Z","git_url":"git://github.com/huangz1990/real-world-haskell-cn.git","ssh_url":"git@github.com:huangz1990/real-world-haskell-cn.git","clone_url":"https://github.com/huangz1990/real-world-haskell-cn.git","svn_url":"https://github.com/huangz1990/real-world-haskell-cn","homepage":"http://rwh.readthedocs.org/","size":1036,"stargazers_count":153,"watchers_count":153,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":33,"mirror_url":null,"open_issues_count":5,"forks":33,"open_issues":5,"watchers":153,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21"},"html":{"href":"https://github.com/huangz1990/real-world-haskell-cn/pull/21"},"issue":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/21"},"comments":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/issues/21/comments"},"review_comments":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21/comments"},"review_comment":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/pulls/21/commits"},"statuses":{"href":"https://api.github.com/repos/huangz1990/real-world-haskell-cn/statuses/ae943c17234734621cd80e4c040ad3a449c1359b"}}}}