changeset 4:3a7df492ae34

add discription for counter
author Daichi TOMA <toma@cr.ie.u-ryukyu.ac.jp>
date Sat, 06 Jul 2013 07:56:31 +0900
parents 50842df0402f
children 69e052c7ef6c
files haskell.html
diffstat 1 files changed, 140 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/haskell.html	Sat Jul 06 06:24:11 2013 +0900
+++ b/haskell.html	Sat Jul 06 07:56:31 2013 +0900
@@ -264,6 +264,7 @@
 				<h3>
           簡単なプログラム
 				</h3>
+        <p>
 <pre>
 {-# LANGUAGE OverloadedStrings #-}
 import Network.Wai
@@ -275,7 +276,6 @@
 
 main = run 3000 application
 </pre>
-        <p>
           このソースコードを読み解いていきます。
         </p>
         <p>
@@ -335,7 +335,7 @@
 <pre>
 ghci&gt; :i Application
 type Application =
-  Request -&gt; Control.Monad.Trans.Resource.ResourceT IO Response
+  Request -&gt; ResourceT IO Response
 </pre>
         <p>
           Monad に包まれていて少しわかりにくいですが、端的に言えば Request を受け取って Response を返す関数を表しています。
@@ -396,7 +396,7 @@
           responseLBS とは?
         </h3>
 <pre>
-Prelude Network.Wai.Handler.Warp Network.Wai Network.HTTP.Types&gt; :t responseLBS
+ghci&gt; :t responseLBS
 responseLBS
   :: Status
      -&gt; ResponseHeaders
@@ -515,7 +515,7 @@
           作成するプログラム全容
         </h3>
         <p>
-          <a href="https://gist.github.com/amothic/5933808">Source Code</a>
+          <a href="https://gist.github.com/amothic/5933808">routes.hs</a>
 <pre>
 application request = return $
     routes $ pathInfo request
@@ -637,7 +637,7 @@
           完成!
         </h3>
         <p>
-          <a href="https://gist.github.com/amothic/5933808">Source Code</a>
+          <a href="https://gist.github.com/amothic/5933808">routes.hs</a>
 <pre>
 application request = return $
     routes $ pathInfo request
@@ -764,6 +764,141 @@
 
 			<article>
         <h3>
+          では、このIORefを使ってCounterを作りましょう!
+        </h3>
+        <p>
+<pre>
+-- IORef Int という型のデータを作製する
+counter &lt;- newIORef 0
+
+-- データの更新を atomic に行う
+-- atomicModifyIORef には、更新したい IORef a 型の変数と、
+-- IORef が持つ値を受け取って 
+-- ( 更新後の値, 戻り値にしたい値 ) というタプルを返す関数を渡す
+incCount:: IORef a -&gt; IO a
+incCount counter = atomicModifyIORef counter (\c -&gt; (c+1, c))
+
+-- 現在のデータの値を受け取る
+currentNum &lt;- readIORef counter
+</pre>
+        </p>
+			</article>
+
+			<article class="smaller">
+        <h3>
+          プログラム全容
+        </h3>
+        <p>
+          <a href="https://gist.github.com/amothic/5937576">counter.hs</a>
+<pre>
+{-# LANGUAGE OverloadedStrings #-}
+import Network.Wai
+import Network.HTTP.Types (status200)
+import Network.Wai.Handler.Warp (run)
+import Control.Monad.Trans (liftIO, lift)
+import Data.IORef (newIORef, atomicModifyIORef)
+import Data.ByteString.Lazy.UTF8 (fromString)
+
+application counter request = do
+  count &lt;- lift $ incCount counter
+  return $ responseLBS status200 [("Content-type", "text/html")] $
+      fromString $ show count
+
+incCount counter = atomicModifyIORef counter (\c -&gt; (c+1, c))
+
+main = do 
+  counter &lt;- newIORef 0
+  run 3000 $ application counter
+</pre>
+        </p>
+			</article>
+
+			<article>
+        <h3>
+          main
+        </h3>
+        <p>
+          mainでは、counterの初期化を行なっています。
+        </p>
+        <p>
+          それをrunとdo構文で糊付けしています。
+        </p>
+<pre>
+main = do 
+  counter &lt;- newIORef 0
+  run 3000 $ application counter
+</pre>
+      </article>
+
+			<article>
+        <h3>
+          application
+        </h3>
+        <p>
+          applicationでは、引数をひとつ増やして、初期化されたIORefを受け取れるようにしています。
+        </p>
+        <p>
+          また、incCountを、ResourceTのモナド内に持ち込むためliftを行なっています。
+        </p>
+        <p>
+          incCountでは、atomicModifyIORefを使って、counterをインクリメントしています。
+        </p>
+<pre>
+application counter request = do
+  count &lt;- lift $ incCount counter
+  return $ responseLBS status200 [("Content-type", "text/html")] $
+      fromString $ show count
+
+incCount counter = atomicModifyIORef counter (\c -&gt; (c+1, c))
+</pre>
+      </article>
+
+			<article class="smaller">
+        <h3>
+          完成!
+        </h3>
+        <p>
+          <a href="https://gist.github.com/amothic/5937576">counter.hs</a>
+<pre>
+{-# LANGUAGE OverloadedStrings #-}
+import Network.Wai
+import Network.HTTP.Types (status200)
+import Network.Wai.Handler.Warp (run)
+import Control.Monad.Trans (liftIO, lift)
+import Data.IORef (newIORef, atomicModifyIORef)
+import Data.ByteString.Lazy.UTF8 (fromString)
+
+application counter request = do
+  count &lt;- lift $ incCount counter
+  return $ responseLBS status200 [("Content-type", "text/html")] $
+      fromString $ show count
+
+incCount counter = atomicModifyIORef counter (\c -&gt; (c+1, c))
+
+main = do 
+  counter &lt;- newIORef 0
+  run 3000 $ application counter
+</pre>
+        </p>
+			</article>
+
+			<article>
+        <h3>
+          実行
+        </h3>
+        <p>
+          <a href="http://localhost:3000/">http://localhost:3000/</a>
+        </p>
+        <p>
+          アクセスするたびに表示される数字がインクリメントされていくはずです。
+        </p>
+        <p>
+          Chromeだと、毎回faviconにアクセスされるせいで、countが+2されていきます…
+        </p>
+      </article>
+
+			<article>
+        <h3>
           そして気づくことなど
         </h3>
         <p>