<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[BLOG dayo]]></title><description><![CDATA[nodejs, haskellなど]]></description><link>http://blog.nakaji.me/</link><generator>Ghost 0.11</generator><lastBuildDate>Thu, 17 Jun 2021 08:06:49 GMT</lastBuildDate><atom:link href="http://blog.nakaji.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[zenn: Type level mapを使ったpreload風関連リソースの取り回し。Indexed monad添え]]></title><description><![CDATA[<p>zennに記事書いた。 <br>
一応まとめとく。</p>

<p><a href="https://zenn.dev/nakaji_dayo/articles/999e41568ce0bd">Type level mapを使ったpreload風関連リソースの取り回し。Indexed monad添え
</a></p>]]></description><link>http://blog.nakaji.me/untitled-11/</link><guid isPermaLink="false">bb5cd454-f71c-4a9e-8a8b-27bee5c66b7e</guid><category><![CDATA[Haskell]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sun, 03 Jan 2021 06:01:58 GMT</pubDate><content:encoded><![CDATA[<p>zennに記事書いた。 <br>
一応まとめとく。</p>

<p><a href="https://zenn.dev/nakaji_dayo/articles/999e41568ce0bd">Type level mapを使ったpreload風関連リソースの取り回し。Indexed monad添え
</a></p>]]></content:encoded></item><item><title><![CDATA[haskell-language-server+emacsでのハマりどころ2020年夏]]></title><description><![CDATA[<h3 id="setuphs">Setup.hs</h3>

<p>Setup.hsに対するエラー <br>
prefix not foundみたいなのや、エラーがログからは見当たらなかったりするが、とにかくfaied filesのSetup.hsが入る</p>

<p>次のhie.yamlでSetup.hsは解決した</p>

<pre><code>cradle:  
  multi:
    - path: "./"
      config:
        cradle:
          stack:
            - path: "./src"
              component: "cooking-recipe-dsl:lib"
            - path: "./app/Main.hs"
              component: "cooking-recipe-dsl:exe:cooking-recipe-dsl-exe"
            - path: "./app/Paths_cooking_recipe_dsl.hs"
              component: "cooking-recipe-dsl:exe:cooking-recipe-dsl-exe"
            - path:</code></pre>]]></description><link>http://blog.nakaji.me/haskell-language-server-emacs-2020-summer/</link><guid isPermaLink="false">ecfb8870-cfd8-444b-aa6b-c313318d3c7f</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Fri, 31 Jul 2020 16:05:28 GMT</pubDate><content:encoded><![CDATA[<h3 id="setuphs">Setup.hs</h3>

<p>Setup.hsに対するエラー <br>
prefix not foundみたいなのや、エラーがログからは見当たらなかったりするが、とにかくfaied filesのSetup.hsが入る</p>

<p>次のhie.yamlでSetup.hsは解決した</p>

<pre><code>cradle:  
  multi:
    - path: "./"
      config:
        cradle:
          stack:
            - path: "./src"
              component: "cooking-recipe-dsl:lib"
            - path: "./app/Main.hs"
              component: "cooking-recipe-dsl:exe:cooking-recipe-dsl-exe"
            - path: "./app/Paths_cooking_recipe_dsl.hs"
              component: "cooking-recipe-dsl:exe:cooking-recipe-dsl-exe"
            - path: "./test"
              component: "cooking-recipe-dsl:test:cooking-recipe-dsl-test"
    - path: ./Setup.hs
      config:
        cradle:
          direct:
            arguments:
              - "-package Cabal"
              - "-package base"
</code></pre>

<h2 id="rootdir">rootDirがおかしいっぽい</h2>

<pre><code>Module "/home/daishi/a" is loaded by Cradle: Cradle {cradleRootDir = "/home/daishi", cradleOptsProg = CradleAction: Default}  
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper) Version 0.2.2.0, Git revision 4fe0f7dfc1cac850a1a1a201fff41cdecc0fb7cf (423 commits) x86_64 ghc-8.8.4  
Current directory: /home/daishi  
Operating system: linux  
Arguments: ["--lsp","-d","-l","/tmp/hie.log"]  
Cradle directory: /home/daishi  
Cradle type: Default  
Consulting the cradle to get project GHC version...  
Cradle requires ghc but couldn't find it  
Cradle {cradleRootDir = "/home/daishi", cradleOptsProg = CradleAction: Default}

Process hie stderr finished
</code></pre>

<p><code>haskell-language-server-wrapper</code>を止めてバージョン込みで直接<code>haskell-language-server-x.y.z</code>を指定したら直った.</p>]]></content:encoded></item><item><title><![CDATA[make emacs 27]]></title><description><![CDATA[<p>native json supportが使いたい！！！</p>

<pre><code>./autogen.sh
sudo zypper in libjansson-devel  
sudo zypper in makeinfo  
sudo zypper in libgnutls-devel  
./configure --with-json --without-x
</code></pre>]]></description><link>http://blog.nakaji.me/make-emacs-27/</link><guid isPermaLink="false">001d29a9-78d0-45bc-8dbd-c8208cace127</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Fri, 22 May 2020 01:25:27 GMT</pubDate><content:encoded><![CDATA[<p>native json supportが使いたい！！！</p>

<pre><code>./autogen.sh
sudo zypper in libjansson-devel  
sudo zypper in makeinfo  
sudo zypper in libgnutls-devel  
./configure --with-json --without-x
</code></pre>]]></content:encoded></item><item><title><![CDATA[ApplicativeDo拡張を試す]]></title><description><![CDATA[<p>ApplicativeDoの動作を実際に動かして見てみたいと思いました。</p>

<p>解説は以下などで行われています。 <br>
どのようにdesugarされるかもわかります。</p>

<ul>
<li><a href="https://gitlab.haskell.org/ghc/ghc/-/wikis/applicative-do">https://gitlab.haskell.org/ghc/ghc/-/wikis/applicative-do</a></li>
<li><a href="https://qiita.com/thimura/items/120f40c4e49f9154ac8a">https://qiita.com/thimura/items/120f40c4e49f9154ac8a</a></li>
</ul>

<p>&lt;*>と>>=で挙動が違う適当な型を用意して、</p>

<pre><code class="language-haskell">{-# LANGUAGE ApplicativeDo #-}

import           Control.Monad

newtype Branch a = Branch { runBranch :: (a, [[String]]) }  
  deriving (Show)
instance Functor Branch where  
  fmap = liftM

instance Applicative Branch where  
  pure = return
  Branch</code></pre>]]></description><link>http://blog.nakaji.me/applicativedokuo-zhang-woshi-su/</link><guid isPermaLink="false">8e14d9d7-2a99-46aa-8e91-9630abdbcb1e</guid><category><![CDATA[Haskell]]></category><category><![CDATA[Programming]]></category><category><![CDATA[GHC]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Wed, 29 Apr 2020 18:43:30 GMT</pubDate><content:encoded><![CDATA[<p>ApplicativeDoの動作を実際に動かして見てみたいと思いました。</p>

<p>解説は以下などで行われています。 <br>
どのようにdesugarされるかもわかります。</p>

<ul>
<li><a href="https://gitlab.haskell.org/ghc/ghc/-/wikis/applicative-do">https://gitlab.haskell.org/ghc/ghc/-/wikis/applicative-do</a></li>
<li><a href="https://qiita.com/thimura/items/120f40c4e49f9154ac8a">https://qiita.com/thimura/items/120f40c4e49f9154ac8a</a></li>
</ul>

<p>&lt;*>と>>=で挙動が違う適当な型を用意して、</p>

<pre><code class="language-haskell">{-# LANGUAGE ApplicativeDo #-}

import           Control.Monad

newtype Branch a = Branch { runBranch :: (a, [[String]]) }  
  deriving (Show)
instance Functor Branch where  
  fmap = liftM

instance Applicative Branch where  
  pure = return
  Branch (f, x:v) &lt;*&gt; Branch (y, x':v') =
    Branch (f y, ((x ++ x'):v') ++ v)

instance Monad Branch where  
    return x = Branch (x, mempty)
    (Branch (x,v)) &gt;&gt;= f =
      let (Branch (y, v')) = f x
      in Branch (y, v ++ v')

runBranch' = snd . runBranch

num x = do  
  Branch (x, [[show x]])
  pure x
</code></pre>

<p>サンプルにあるパターンを実行してみる。</p>

<pre><code class="language-haskell">-- [["5","6"]]
f1 = runBranch' $ do  
  x &lt;- num 5
  y &lt;- num 6
  pure $ x+y
</code></pre>

<p>拡張を切れば <code>[["5"], ["6"]]</code> となる</p>

<p>全部試す。</p>

<pre><code class="language-hs">-- [["1","2"],["3"]]
f2 = runBranch' $ do  
  x &lt;- num 1
  y &lt;- num 2
  num (x + y)

-- [["5","6"],["15","16"]]
f3 = runBranch' $ do  
  x &lt;- num 5
  x' &lt;- num 6
  y &lt;- num (x+10)
  y' &lt;- num (x'+10)
  pure $ x+y+x'+y'

-- [["5","7"],["6"]]
f4 = runBranch' $ do  
  x &lt;- num 5
  y &lt;- num (x+1)
  z &lt;- num 7
  pure $ x+y+z

-- [["5","6","7"],["105"]]
f5 = runBranch' $ do  
  x &lt;- num 5
  x' &lt;- num 6
  y &lt;- num (x+100)
  x'' &lt;- num 7
  pure $ x'+x''+y
</code></pre>

<p>すごい！完</p>]]></content:encoded></item><item><title><![CDATA[HRRで主キー、外部キーごとに新しく型を割り当ててみた(雑)]]></title><description><![CDATA[<p><a href="http://khibino.github.io/haskell-relational-record/">HRR</a>で型安全なクエリをかけるので大満足生活だが、主キー・外部キーがすべて同じ型(Int64等)になってしまっている状況では注意力が必要だと感じた。</p>

<p>どのカラムも型割り当ててもよいのだが、特に次の理由で、</p>

<ul>
<li>query作成時に指定することが多いはずなため</li>
<li>関連していないidは比較できないと考えて良かったため</li>
</ul>

<h3 id="">前置き</h3>

<p>雑なコード生成で殴ってます。 <br>
コード生成良くないが、hrr使ってる関連では既にTableごとのモジュールのコード生成を行ってたので、考えることをやめた。</p>

<h3 id="">実装内容</h3>

<p>shell scriptでpostgresのinformation_schemaへの問い合わせを使い次のようなコードを生成した。</p>

<ul>
<li>PKごとにnewtypeを定義を生成</li>
<li>カラムごとに型を割り当てるため、<a href="https://hackage.haskell.org/package/relational-query-HDBC-0.7.2.0/docs/Database-HDBC-Schema-Driver.html#t:Driver">getFieldsWithMap</a>の挙動の一部を上書きする関数を生成</li>
</ul>

<p><code>pkごとにnewtype生成する例.sh</code></p>

<pre><code>query=$(cat &lt;&lt; EOS  
SELECT  
    tc.table_name,
    kcu.column_name
FROM  
    information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage</code></pre>]]></description><link>http://blog.nakaji.me/hrr-pk-fk-newtype/</link><guid isPermaLink="false">a1ab4168-1fc0-4575-909f-ec0e2d842ad4</guid><category><![CDATA[Haskell]]></category><category><![CDATA[HRR]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sat, 29 Jun 2019 07:28:33 GMT</pubDate><content:encoded><![CDATA[<p><a href="http://khibino.github.io/haskell-relational-record/">HRR</a>で型安全なクエリをかけるので大満足生活だが、主キー・外部キーがすべて同じ型(Int64等)になってしまっている状況では注意力が必要だと感じた。</p>

<p>どのカラムも型割り当ててもよいのだが、特に次の理由で、</p>

<ul>
<li>query作成時に指定することが多いはずなため</li>
<li>関連していないidは比較できないと考えて良かったため</li>
</ul>

<h3 id="">前置き</h3>

<p>雑なコード生成で殴ってます。 <br>
コード生成良くないが、hrr使ってる関連では既にTableごとのモジュールのコード生成を行ってたので、考えることをやめた。</p>

<h3 id="">実装内容</h3>

<p>shell scriptでpostgresのinformation_schemaへの問い合わせを使い次のようなコードを生成した。</p>

<ul>
<li>PKごとにnewtypeを定義を生成</li>
<li>カラムごとに型を割り当てるため、<a href="https://hackage.haskell.org/package/relational-query-HDBC-0.7.2.0/docs/Database-HDBC-Schema-Driver.html#t:Driver">getFieldsWithMap</a>の挙動の一部を上書きする関数を生成</li>
</ul>

<p><code>pkごとにnewtype生成する例.sh</code></p>

<pre><code>query=$(cat &lt;&lt; EOS  
SELECT  
    tc.table_name,
    kcu.column_name
FROM  
    information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
      AND tc.table_schema = kcu.table_schema
WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_name &lt;&gt; 'schema_migrations';  
EOS  
)
IFS='|'  
psql -h localhost -d ${DB} -U api -Atc "$query" \  
    | while read tbl clm; do
        entity=`echo $tbl | perl -pe "s/_(.)/\u\1/g; s/^(.)/\u\1/g"`
        cat &gt;&gt; $entityId &lt;&lt; EOS
newtype ${entity}Id = ${entity}Id { un${entity}Id :: Int64 }  
  deriving (Generic, Eq, Show, ToJSON, FromJSON, Default, Arbitrary, PersistableWidth
           , LiteralSQL, FromSql SqlValue, ToSql SqlValue, FromHttpApiData, Num)

EOS

done  
</code></pre>

<p><code>PK,FKに上記の型を割り当てるgetFieldsWithMapを生成する例.sh</code></p>

<pre><code>echo "getField' :: String -&gt; (String, TypeQ) -&gt; (String, TypeQ)" &gt;&gt; $entityId  
psql -h localhost -d ${DB} -U api -Atc "$query" \  
    | while read tbl clm; do
        entity=`echo $tbl | perl -pe "s/_(.)/\u\1/g; s/^(.)/\u\1/g"`
        echo "getField' \"${tbl}\" (c@\"${clm}\", _) = (c, [t|${entity}Id|])" &gt;&gt; $entityId
    done

### FK
query=$(cat &lt;&lt; EOS  
SELECT  
    tc.table_name,
    kcu.column_name,
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name
FROM  
    information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
      AND tc.table_schema = kcu.table_schema
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
      AND ccu.table_schema = tc.table_schema
WHERE tc.constraint_type = 'FOREIGN KEY';  
EOS  
     )
psql -h localhost -d ${DB} -U api -Atc "$query" \  
    | while read tbl clm ftbl fclm; do
    fentity=`echo $ftbl | perl -pe "s/_(.)/\u\1/g; s/^(.)/\u\1/g"`
    echo "getField' \"${tbl}\" (c@\"${clm}\", _) = (c, [t|${fentity}Id|])" &gt;&gt; $entityId
done  
echo "getField' _ x = x" &gt;&gt; $entityId  
</code></pre>

<p><code>こんなのが生成されました.hs</code></p>

<pre><code>newtype UserId = UserId { unUserId :: Int64 }  
  deriving (Generic, Eq, Show, ToJSON, FromJSON, Default, Arbitrary, PersistableWidth
           , LiteralSQL, FromSql SqlValue, ToSql SqlValue, FromHttpApiData, Num)
newtype TaskId = TaskId { unTaskId :: Int64 }  
  deriving (Generic, Eq, Show, ToJSON, FromJSON, Default, Arbitrary, PersistableWidth
           , LiteralSQL, FromSql SqlValue, ToSql SqlValue, FromHttpApiData, Num)

getField' :: String -&gt; (String, TypeQ) -&gt; (String, TypeQ)  
getField' "user" (c@"id", _) = (c, [t|UserId|])  
getField' "task" (c@"id", _) = (c, [t|TaskId|])  
getField' "task" (c@"user_id", _) = (c, [t|UserId|])  
getField' _ x = x
</code></pre>

<h2 id="">使用感</h2>

<p>placeholderにid渡すときに型残せるし、query内のオペレータでId使うときも安全。</p>

<pre><code>selectTasks :: Query UserId Task  
selectTasks = relation' . placeholder $ \ph -&gt; do  
  t &lt;- query task
  -- x &lt;- query ...
  -- on $ x ! #taskId .=. t ! #id
  wheres $ t ! #userId .=. ph
  pure p
</code></pre>

<p>因みに、servant使ってるので、routingから一貫してId使える。</p>

<pre><code>"users" :&gt; Capture "id" UserId :&gt; "tasks"
</code></pre>

<h3 id="">感想</h3>

<ul>
<li>この実装についてhrr作者の日比野さんに伺った所、「型は自分で書いて、それを名前のルールに従って対応付けられるように<code>getFieldsWithMap</code>を生成する」という使い方をしてた、と仰っていた。
<ul><li>確かにPK,FKとか関係なく、どこまで型分けたいかは設計次第なので、汎用性のある方法考えたい。しかし考えていくと、テーブル定義する時点でHaskell側に型が欲しくなる気がしている。</li></ul></li>
<li>今と同じことやるにしても、THやGenericsでなんとかしたい</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Aesonのjsonのparseで「nullが指定されている」と「キーが存在しない」を区別する]]></title><description><![CDATA[<h1 id="aesonjsonparsenull">Aesonのjsonのparseで「nullが指定されている」と「キーが存在しない」を区別する</h1>

<p><code>.:!</code>を使えば良い</p>

<pre><code class="language-`">{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

import           Data.Aeson  
import           GHC.Generics

data PatchTest = PatchTest  
  { f1 :: Maybe (Maybe String)
  } deriving (Show, Generic)
instance FromJSON PatchTest where  
    parseJSON (Object v) =  PatchTest &lt;$&gt; v .:! "f1"

f = mapM_ (putStrLn.show) (  
  [ decode "{\"f1\": \"test\"}"
  , decode</code></pre>]]></description><link>http://blog.nakaji.me/untitled-6/</link><guid isPermaLink="false">ed83ef1e-18b3-4a98-804e-94fa5d17c5f9</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sat, 10 Nov 2018 10:58:08 GMT</pubDate><content:encoded><![CDATA[<h1 id="aesonjsonparsenull">Aesonのjsonのparseで「nullが指定されている」と「キーが存在しない」を区別する</h1>

<p><code>.:!</code>を使えば良い</p>

<pre><code class="language-`">{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

import           Data.Aeson  
import           GHC.Generics

data PatchTest = PatchTest  
  { f1 :: Maybe (Maybe String)
  } deriving (Show, Generic)
instance FromJSON PatchTest where  
    parseJSON (Object v) =  PatchTest &lt;$&gt; v .:! "f1"

f = mapM_ (putStrLn.show) (  
  [ decode "{\"f1\": \"test\"}"
  , decode "{\"f1\": null}"
  , decode "{}"] :: [Maybe PatchTest])
</code></pre>

<pre><code>Just (PatchTest {f1 = Just (Just "test")})  
Just (PatchTest {f1 = Just Nothing})  
Just (PatchTest {f1 = Nothing})  
</code></pre>]]></content:encoded></item><item><title><![CDATA[gitによるversionを取得するAPIを追加]]></title><description><![CDATA[<p><a href="https://hackage.haskell.org/package/gitrev-1.3.1">gitrev</a>を使ってjsonを作る</p>

<pre><code>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
module Version where

import Data.Aeson  
import Development.GitRev  
import GHC.Generics

data LibVersion = LibVersion  
  { branch :: String
  , commit  :: String
  , dirty :: Bool
  } deriving (Generic, Show)

instance ToJSON LibVersion  
instance FromJSON LibVersion

libVersion :: LibVersion  
</code></pre>

<p>これをservantか何かで提供する。</p>

<pre><code>getVersion :: Handler LibVersion  
getVersion = return libVersion  
</code></pre>

<p>多分社内用のAPIとかに便利。</p>]]></description><link>http://blog.nakaji.me/gitniyoruversionwoqu-de-suruapiwozhui-jia/</link><guid isPermaLink="false">1b96507e-964a-4a22-96eb-599c646d9000</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Fri, 29 Dec 2017 07:23:38 GMT</pubDate><content:encoded><![CDATA[<p><a href="https://hackage.haskell.org/package/gitrev-1.3.1">gitrev</a>を使ってjsonを作る</p>

<pre><code>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
module Version where

import Data.Aeson  
import Development.GitRev  
import GHC.Generics

data LibVersion = LibVersion  
  { branch :: String
  , commit  :: String
  , dirty :: Bool
  } deriving (Generic, Show)

instance ToJSON LibVersion  
instance FromJSON LibVersion

libVersion :: LibVersion  
</code></pre>

<p>これをservantか何かで提供する。</p>

<pre><code>getVersion :: Handler LibVersion  
getVersion = return libVersion  
</code></pre>

<p>多分社内用のAPIとかに便利。</p>

<pre><code>$ curl http://localhost:8080/version
{"dirty":true,"branch":"master","commit":"xxxxxxxxxxx"}
</code></pre>]]></content:encoded></item><item><title><![CDATA[slack-api + bloodhound + servant でbot+αを作る]]></title><description><![CDATA[<p><a href="https://qiita.com/advent-calendar/2017/haskell2">Haskell (その2) Advent Calendar 2017</a> (7日目)の記事です。</p>

<ul>
<li>Advent Calendarのネタ探しに何か作ろうと思った。</li>
<li>slack上のQA形式の知見を手動でまとめていき、後から参照しやすくするbotを作りたいと思った。</li>
<li>(リリースまで行けなかった。次の休みには公開してリンク貼ります。。無念　)　=> 追記2017-12-29: 作ったやつ => <a href="https://slacknowledge.pig-brewing.com/">https://slacknowledge.pig-brewing.com/</a></li>
</ul>

<p>特にすごいことはなく普通にサービスを作ってしまったので、使ったライブラリとその使い方などを紹介したいと思います。</p>

<p>主なやったことは次の３点:</p>

<ul>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#slackbot">slack botを作る</a>
<ul><li>slack-api packageが便利</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#elasticsearch">Elasticsearchに保存・検索</a>
<ul><li>bloodhound packageが便利</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#website">web site作る</a>
<ul><li>servantでweb front作った</li>
<li>api(servant) + spa等では無いのが(私の中で)新鮮</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#ghcihotreload">ghciを使ってhot reloadしながら素早く開発する　(おまけ)</a>
<ul><li>rapidが便利</li></ul></li>
</ul>

<h3 id="slackbot">slack botを作る</h3>

<ul>
<li><a href="https://github.com/mpickering/slack-api">slack-api</a>を使った</li>
</ul>

<p>Slack</p>]]></description><link>http://blog.nakaji.me/slack-api-bloodhound-servant/</link><guid isPermaLink="false">019956fa-2dbd-4077-8664-9546097e4ff9</guid><category><![CDATA[Haskell]]></category><category><![CDATA[slack]]></category><category><![CDATA[bloodhound]]></category><category><![CDATA[servant]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Thu, 07 Dec 2017 17:27:24 GMT</pubDate><content:encoded><![CDATA[<p><a href="https://qiita.com/advent-calendar/2017/haskell2">Haskell (その2) Advent Calendar 2017</a> (7日目)の記事です。</p>

<ul>
<li>Advent Calendarのネタ探しに何か作ろうと思った。</li>
<li>slack上のQA形式の知見を手動でまとめていき、後から参照しやすくするbotを作りたいと思った。</li>
<li>(リリースまで行けなかった。次の休みには公開してリンク貼ります。。無念　)　=> 追記2017-12-29: 作ったやつ => <a href="https://slacknowledge.pig-brewing.com/">https://slacknowledge.pig-brewing.com/</a></li>
</ul>

<p>特にすごいことはなく普通にサービスを作ってしまったので、使ったライブラリとその使い方などを紹介したいと思います。</p>

<p>主なやったことは次の３点:</p>

<ul>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#slackbot">slack botを作る</a>
<ul><li>slack-api packageが便利</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#elasticsearch">Elasticsearchに保存・検索</a>
<ul><li>bloodhound packageが便利</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#website">web site作る</a>
<ul><li>servantでweb front作った</li>
<li>api(servant) + spa等では無いのが(私の中で)新鮮</li></ul></li>
<li><a href="http://blog.nakaji.me/slack-api-bloodhound-servant/#ghcihotreload">ghciを使ってhot reloadしながら素早く開発する　(おまけ)</a>
<ul><li>rapidが便利</li></ul></li>
</ul>

<h3 id="slackbot">slack botを作る</h3>

<ul>
<li><a href="https://github.com/mpickering/slack-api">slack-api</a>を使った</li>
</ul>

<p>Slack RTM APIのbinding。</p>

<h4 id="">入れる</h4>

<p>stackageにはないのでcommit指定。masterを使ったほうが良い。</p>

<p>stack.yaml  </p>

<pre><code>- location:
    git: https://github.com/mpickering/slack-api.git
    commit: 1240e45490925fe0211a81c553a38d39c47058cd
</code></pre>

<h4 id="bot">botの動かし方</h4>

<ul>
<li>repositoryのexampleがわかりやすい</li>
<li><code>getNextEvent</code>し続ける関数を作り、それを<code>withSlackHandle</code>で実行する</li>
<li><code>getNextEvent</code>が返す<code>Event</code>に対してパターンマッチしてやりたいことをやる</li>
</ul>

<pre><code>knowledgeBot :: SlackHandle -&gt; IO ()  
knowledgeBot h = forever $ do  
  getNextEvent h &gt;&gt;= \case
    (ReactionAdded _ "memo" _ (EmbeddedMessageItem cid msg_ts) _) -&gt; -- reactionが追加された時の処理

-- withSlackHandle conf knowledgeBot
</code></pre>

<ul>
<li><code>withSlackHandle</code>で必要になる<code>SlackConfig</code>にはApiTokenの指定が必要。
<a href="https://api.slack.com/apps">slackでAppを作り</a>"Bot User OAuth Access Token"を使えば良い。</li>
<li>patternが複雑になってきたらpattern synonymを使うと便利(<a href="https://www.schoolofhaskell.com/user/icelandj/Pattern%20synonyms">Pattern Synonyms for Dates and an IRC Bot</a>)</li>
</ul>

<h4 id="botapi">bot以外のAPIを叩く</h4>

<p>slack-apiを使って他のapiも叩いてみる</p>

<ul>
<li>slackのAppの設定から各種permissionを設定</li>
<li>confにはOAuth Access Token(botではない)を使う</li>
</ul>

<p>例えばusers.infoの取得</p>

<pre><code>data UserInfo = UserInfo  
  { _userInfoUser :: User -- Userはslack-apiに定義されている
  } deriving (Generic, Show)
instance FromJSON UserInfo where  
  parseJSON = genericParseJSON $ defaultOptions {fieldLabelModifier = toSnake . drop 9}
</code></pre>

<pre><code>getUser  
    :: (MonadError T.Text m, MonadIO m)
    =&gt; SlackConfig
    -&gt; UserId
    -&gt; m UserInfo
getUser conf (Id uid) = do  
  res &lt;- makeSlackCall conf "users.info" $
    (W.param "user"     .~ [uid])
  fromJSON' res

fromJSON' :: (FromJSON a, MonadError T.Text m) =&gt; Value -&gt; m a  
fromJSON' x = case fromJSON x of  
    Error e -&gt; throwError (T.pack e)
    Success r -&gt; return r
</code></pre>

<h3 id="elasticsearch">Elasticsearchに保存・検索</h3>

<ul>
<li><p><a href="https://hackage.haskell.org/package/bloodhound-0.14.0.0">bloodhound</a>を使用</p></li>
<li><p>Elasticsearchのclientライブラリ。5系にも対応している</p></li>
<li>こちらもrepositoryのexampleがわかりやすい。 </li>
<li>後はちゃんと型を見て使う</li>
</ul>

<h4 id="index">indexの設定</h4>

<ul>
<li>各種設定値</li>
</ul>

<pre><code>runBH' = withBH defaultManagerSettings server

migration :: IO()  
migration = runBH' $ do  
  _ &lt;- createIndex indexSettings index
  True &lt;- indexExists index
  rs &lt;-  putMapping index threadMapping ThreadMapping
  liftIO $ print rs

server = (Server "http://localhost:9200")  
index = IndexName "hogehoge"  
indexSettings = IndexSettings (ShardCount 1) (ReplicaCount 0)  
threadMapping = MappingName "thread"

data ThreadMapping = ThreadMapping deriving (Eq, Show)

instance ToJSON ThreadMapping where  
  toJSON _ =
    [aesonQQ|
{
  "properties": {
    "ts": {
      "type": "double"
    },
    "tags": {
      "type": "string",
      "index": "not_analyzed"
    }
  }
}
|]
</code></pre>

<ul>
<li>mapping設定に<code>Data.Aeson.QQ</code>が便利</li>
</ul>

<h4 id="documentindex">Documentをindex</h4>

<ul>
<li>jsonにできるものと、　DocIdを渡す</li>
</ul>

<pre><code>indexThread :: Thread -&gt; IO ()  
indexThread thread = runBH' $ do  
  res &lt;- indexDocument index threadMapping defaultIndexDocumentSettings
    thread (DocId  (formatSlackTimeStamp $ thread ^. ts))
  liftIO $ print res
</code></pre>

<p>例えば次のような型を扱っている。</p>

<pre><code>data Thread = Thread  
  { _threadTs   :: SlackTimeStamp
  , _threadTags :: [Text]
  } deriving (Generic, Show)
</code></pre>

<p><code>ToJSON</code>と<code>FromJSON</code>にする必要がある。</p>

<h4 id="">検索</h4>

<ul>
<li><code>Search</code>を組み立てて<code>searchByIndex</code>を使う</li>
<li>結果はByteStringだがbloodhoundの<a href="https://hackage.haskell.org/package/bloodhound-0.14.0.0/docs/Database-V5-Bloodhound-Types.html#t:SearchResult">SearchResult</a>にdecodeできる</li>
</ul>

<pre><code>searchThread :: (MonadError String m, MonadIO m) =&gt; Maybe Text -&gt; m [Thread]  
searchThread mtag = do  
  let mquery =　fmap (\tag -&gt; TermQuery (Term "tags" tag) Nothing) mtag
  res &lt;- liftIO . runBH' $ do
    let search = Search
          { queryBody = mquery
          , filterBody = Nothing
          , sortBody = Just [DefaultSortSpec (mkSort (FieldName "ts") Descending)]
          , aggBody = Nothing
          , highlight = Nothing
          , trackSortScores = False
          , from = From 0
          , size = Size 20
          , searchType = SearchTypeQueryThenFetch
          , fields = Nothing
          , source = Nothing
          }
    searchByIndex index search
  case eitherDecode (responseBody res) of
    Right res -&gt; return $ catMaybes $ hitSource &lt;$&gt; (hits . searchHits $ res)
    Left e -&gt; throwError e
</code></pre>

<ul>
<li>ここでは雑にsourceだけを取り出している</li>
</ul>

<h2 id="website">web site作る</h2>

<ul>
<li><a href="https://hackage.haskell.org/package/servant">servant</a>を使用</li>
</ul>

<p>servantでWebページ作る</p>

<ul>
<li>htmlをレスポンスするには<code>Text.Blaze.Markup</code>を使う</li>
<li>template engineには<a href="https://hackage.haskell.org/package/heterocephalus-1.0.5.1">heterocephalus</a>を使用</li>
</ul>

<pre><code>type API = Get '[HTML] Markup  
  :&lt;|&gt; "search" :&gt; QueryParam "tag" Text :&gt; Get '[HTML] Markup

api :: Proxy API  
api = Proxy

server :: Server API  
server = (searchR Nothing)  
         :&lt;|&gt; searchR

searchR :: Maybe Text -&gt; Handler Markup  
searchR mtag = do  
  ethreads &lt;- liftIO $ runExceptT $ ES.searchThread mtag
  return $ case ethreads of
    Right threads -&gt; $(compileTextFile "templates/index.html")
    Left e -&gt;  $(compileTextFile "templates/500.html")
</code></pre>

<h2 id="ghcihotreload">ghciを使ってhot reloadしながら素早く開発する　（おまけ）</h2>

<p>細かくpreviewしながら作る必要がある物だとビルドに時間がかかってはたまらない。 <br>
haskellにはghci(インタプリタ)があるのでそういうときも困らない。</p>

<p>関数を実行して試すだけなら、ghciでmoduleをloadして関数を呼ぶだけ。 <br>
下記はapi,botのようにプロセス起動しっぱなしにしときつつreloadしたい時の話。</p>

<p><a href="https://hackage.haskell.org/package/rapid">rapid</a>というpackageを使用した。</p>

<pre><code>module Main where

import Rapid  
import qualified Slacknowledge.Api as Api  
import qualified Slacknowledge.Bot as Bot

main = return ()

up :: IO ()  
up = rapid 0 $ \r -&gt; do  
  restart r "api" Api.startApp
  restart r "bot" Bot.run
</code></pre>

<p>cabalにexecutableを追加して、これを読み込んで実行する構成にしてみた</p>

<p><code>.cabal</code></p>

<pre><code>executable slacknowledge-devel  
  hs-source-dirs:      app
  main-is:             DevelMain.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , slacknowledge
                     , rapid
  default-language:    Haskell2010
</code></pre>

<h4 id="">使う</h4>

<pre><code>stack ghci slacknowledge:lib slacknowledge:exe:slacknowledge-devel  
&gt; up
listen 8080  
&gt; :r
&gt; up
</code></pre>

<p>速い！</p>

<hr>

<p>2017-12-29: 追記</p>

<h4 id="ghcidautoreload">ghcidを使ってauto reload</h4>

<pre><code>ghcid --command="stack ghci slacknowledge:lib slacknowledge:exe:slacknowledge-devel" --reload=./templates/ --reload=src --test up  
</code></pre>

<p>もっと速い！</p>]]></content:encoded></item><item><title><![CDATA[HaskellでSESを使って添付ファイル付メールを送る]]></title><description><![CDATA[<p>SESでのメール送信に関連するライブラリの紹介記事です。</p>

<p>SESで添付ファイル付メールを送るには<a href="http://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html">SendRawEmail</a>アクションを使用する。この時メールのフォーマットを組み立てる必要が有るため、自力で全部やるのは厳しい。</p>

<p>次のライブラリを使用した。</p>

<ul>
<li>amazonka-ses, amazonka
<ul><li>包括的なAWSのSDK。その内のSESに対するアクション。</li></ul></li>
<li>mime-mail
<ul><li>MIMEを扱うためのライブラリ。これを使い<code>SendRawEmail</code>に送るメールのデータを作成する。</li></ul></li>
<li>heterocephalus
<ul><li>型安全なテンプレートエンジン。本題からはそれるが、メール本文の作成に使用。</li></ul></li>
</ul>

<h2 id="mimemail">mime-mail</h2>

<p><a href="https://hackage.haskell.org/package/mime-mail-0.4.14/docs/Network-Mail-Mime.html#t:Mail">Mail</a> 型の値を組み立てて、renderMailでByteStringを作成（<code>renderMail'</code>でboundaryランダム生成）。</p>

<p><code>Mail</code>の組み立てに幾つかの便利関数が用意されている。</p>

<pre><code>{-# LANGUAGE OverloadedStrings #-}

import Network.Mail.Mime  
import Data.ByteString.Lazy (toStrict)

sample body = do  
  mail &lt;- addAttachment "text/plain"</code></pre>]]></description><link>http://blog.nakaji.me/haskell-ses/</link><guid isPermaLink="false">5500a61a-8082-486c-a91c-5b2e9d204747</guid><category><![CDATA[Haskell]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sun, 05 Nov 2017 05:42:49 GMT</pubDate><content:encoded><![CDATA[<p>SESでのメール送信に関連するライブラリの紹介記事です。</p>

<p>SESで添付ファイル付メールを送るには<a href="http://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html">SendRawEmail</a>アクションを使用する。この時メールのフォーマットを組み立てる必要が有るため、自力で全部やるのは厳しい。</p>

<p>次のライブラリを使用した。</p>

<ul>
<li>amazonka-ses, amazonka
<ul><li>包括的なAWSのSDK。その内のSESに対するアクション。</li></ul></li>
<li>mime-mail
<ul><li>MIMEを扱うためのライブラリ。これを使い<code>SendRawEmail</code>に送るメールのデータを作成する。</li></ul></li>
<li>heterocephalus
<ul><li>型安全なテンプレートエンジン。本題からはそれるが、メール本文の作成に使用。</li></ul></li>
</ul>

<h2 id="mimemail">mime-mail</h2>

<p><a href="https://hackage.haskell.org/package/mime-mail-0.4.14/docs/Network-Mail-Mime.html#t:Mail">Mail</a> 型の値を組み立てて、renderMailでByteStringを作成（<code>renderMail'</code>でboundaryランダム生成）。</p>

<p><code>Mail</code>の組み立てに幾つかの便利関数が用意されている。</p>

<pre><code>{-# LANGUAGE OverloadedStrings #-}

import Network.Mail.Mime  
import Data.ByteString.Lazy (toStrict)

sample body = do  
  mail &lt;- addAttachment "text/plain" "/path/to/file.txt" $ simpleMail' "to@example.com" "from@example.com" "title" body
  msg &lt;- renderMail' mail
  -- ...
</code></pre>

<h2 id="amazonkases">amazonka-ses</h2>

<p>APIへのリクエストに必要な環境を設定して、<a href="https://hackage.haskell.org/package/amazonka-ses-1.4.5/docs/Network-AWS-SES-SendRawEmail.html#v:sendRawEmail">sendRawEmail</a>にメール内容のbytesを渡す。</p>

<p>Discover ではデフォルトの環境変数（<code>AWS_ACCESS_KEY_ID</code>,<code>AWS_SECRET_ACCESS_KEY</code>）の読み込み、それがなければiamのprofile読み込みを行ってくれる。</p>

<pre><code>import Control.Lens  
import Control.Monad.Trans.AWS  
import Network.AWS.SES  
import Control.Monad  
import Data.ByteString.Lazy (toStrict)  
import System.IO

sample = do  
  -- ...
  lgr &lt;- newLogger Debug stdout
  env &lt;- newEnv Discover &lt;&amp;&gt; set envLogger lgr
  runResourceT . runAWST env . within region $ do
    void $ send $ sendRawEmail (rawMessage (toStrict msg))

region = Oregon  
</code></pre>

<h2 id="heterocephalus">heterocephalus</h2>

<p>多分メールは長いのでテキストファイル作って、compileTextFileに渡す。</p>

<pre><code>{-# LANGUAGE TemplateHaskell #-}

import Text.Heterocephalus (compileTextFile)

renderBody name = $(compileTextFile "sample.txt")
</code></pre>

<p>sample.txt  </p>

<pre><code>hello #{name}  
</code></pre>

<pre><code>sample $ renderBody "nakaji-dayo"  
</code></pre>]]></content:encoded></item><item><title><![CDATA[reduxの使い方を考える]]></title><description><![CDATA[<p>業務で何度かreduxを実用している。  </p>

<p>基本reduxは実用的で良いと思っている。 <br>
関数型的な考え方に抵抗があった人も、reduxを使い、思考を変えようとしているように見えるのは驚きだ。</p>

<p>一方、冗長に感じる箇所や妥協で書いてしまうパターンもある。どのように扱っていけばよいのだろうか？</p>

<p>sample repository: <a href="https://github.com/nakaji-dayo/redux-practice">https://github.com/nakaji-dayo/redux-practice</a></p>

<h2 id="action">actionについて</h2>

<p>Actionは代数データ型を表現したかったものである。</p>

<pre><code>// actions.js
const XXX_ACTION = 'XXX_ACTION'  
export const createXxxAction = (x) =&gt; ({  
  type: XXX_ACTION,
  x
})
</code></pre>

<ul>
<li>型 = action.js</li>
<li>コンストラクタ = createXxxAction</li>
<li>他は内部実装</li>
</ul>

<p>jsで普通に書くと明らかに冗長だし、createrに関しても何が嬉しいのかわからない。</p>

<p>いい感じにADTを使え、記述に見合うリターンがある方法を検討する。</p>

<h3 id="">要件</h3>

<ul>
<li>Actionを簡潔に宣言したい</li>
<li>利用時に正しい引数を与えられているかチェックしたい</li>
<li>パタンマッチできたら簡潔にreducerかけてなお良い</li>
</ul>

<h3 id="">選択肢</h3>

<p>-- 要レビュー</p>]]></description><link>http://blog.nakaji.me/redux-practice/</link><guid isPermaLink="false">e44ccbb0-7ab2-44c9-8ce4-77dcd464b487</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Redux]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Wed, 26 Apr 2017 01:45:07 GMT</pubDate><media:content url="http://blog.nakaji.me/content/images/2017/04/logo.png" medium="image"/><content:encoded><![CDATA[<img src="http://blog.nakaji.me/content/images/2017/04/logo.png" alt="reduxの使い方を考える"><p>業務で何度かreduxを実用している。  </p>

<p>基本reduxは実用的で良いと思っている。 <br>
関数型的な考え方に抵抗があった人も、reduxを使い、思考を変えようとしているように見えるのは驚きだ。</p>

<p>一方、冗長に感じる箇所や妥協で書いてしまうパターンもある。どのように扱っていけばよいのだろうか？</p>

<p>sample repository: <a href="https://github.com/nakaji-dayo/redux-practice">https://github.com/nakaji-dayo/redux-practice</a></p>

<h2 id="action">actionについて</h2>

<p>Actionは代数データ型を表現したかったものである。</p>

<pre><code>// actions.js
const XXX_ACTION = 'XXX_ACTION'  
export const createXxxAction = (x) =&gt; ({  
  type: XXX_ACTION,
  x
})
</code></pre>

<ul>
<li>型 = action.js</li>
<li>コンストラクタ = createXxxAction</li>
<li>他は内部実装</li>
</ul>

<p>jsで普通に書くと明らかに冗長だし、createrに関しても何が嬉しいのかわからない。</p>

<p>いい感じにADTを使え、記述に見合うリターンがある方法を検討する。</p>

<h3 id="">要件</h3>

<ul>
<li>Actionを簡潔に宣言したい</li>
<li>利用時に正しい引数を与えられているかチェックしたい</li>
<li>パタンマッチできたら簡潔にreducerかけてなお良い</li>
</ul>

<h3 id="">選択肢</h3>

<p>-- 要レビュー</p>

<ul>
<li>sweet.js
<ul><li>消え行く運命？</li></ul></li>
<li>babel macro
<ul><li>ライブラリ少なくない？</li>
<li>（sweetsも含め）自由にmacro作れる系のもので、それを使ったライブラリが普及するのは無理な気がする。</li></ul></li>
<li>elm
<ul><li>とても期待しているがjsではない</li>
<li>elm-loaderでファイルごとに使うのはできるが、そこで定義したものを使う各所ではチェックできなさそう。</li></ul></li>
<li>flow
<ul><li>jｓの範囲で使える</li>
<li>大きくjsから逸れずに各所で型チェックできそう</li>
<li>syntaxがすごく良くなったりはしない</li></ul></li>
</ul>

<h3 id="flowaction">flowでのactionの改善</h3>

<p>Union Typeを使って、Actionを表現  </p>

<pre><code>/* @flow */

export type Action  
  = {type: "COUNT_UP", value: number}
  | {type: "COUNT_DOWN", value: number}
  | {type: "HOGE", fuga: number}

export type Dispatch = Action =&gt; Action  
</code></pre>

<p>ほぼplainなjsとして使える</p>

<pre><code>const mapDispatchToProps = (dispatch: Dispatch, props) =&gt; ({  
  countUp: () =&gt; {
    dispatch({type: "COUNT_UP", value: 1}) -- valueを指定しないとエラーとなる。
  },
</code></pre>

<p>これも型チェックされる。すごい。</p>

<pre><code>  switch (action.type) {
    case "COUNT_DOWN":
      return {
        ...state,
        count: state.count - action.fuga // error property `fuga`. Property not found.
      }
</code></pre>

<p>Actionの型がチェックされるのはわざわざ宣言するのに足るメリットかと思う。 <br>
Actionのtypeも型レベルの文字列なので、毎回べた書きでも大きな問題はないと考える。クォート打つのは面倒だが。</p>

<h3 id="">余談</h3>

<p>因みに私は、jsのみのプロジェクトでも、ActionCreaterは使わず、dispatch時にオブジェクトを毎回作っている</p>

<pre><code>dispatch({  
  type: XXX,
  x,y,z
})
</code></pre>

<ul>
<li>型チェックされないコンストラクタって何</li>
<li>es2015のproperty name shorthandがあるのでほぼタイプ量変わらない</li>
<li>関数にしておいたほうが使い勝手が良いケースはありそう。出会ってない。</li>
</ul>

<h2 id="component">componentについて</h2>

<p>コンポーネントは可能な限りpure functionにしたい(stateless function componentと呼ぶらしい)。</p>

<ul>
<li>stateを持っていないことが自明</li>
<li>virtual domという仕組みは(現状)必要だが、reactでなければいけないわけではない。</li>
<li>等</li>
</ul>

<p>componentをReact classにする必要があるケース。</p>

<ul>
<li>react componentのlife cycle eventを使いたい時</li>
<li>UIの範囲に閉じていて、他コンポーネントとの影響もない動作の時（言わば「ちょっとしたstate」）</li>
</ul>

<h3 id="">解決方法</h3>

<p><del> React.createClassを関数に入れて頑張る</del></p>

<p>recomposeを使う。 <br>
<a href="https://github.com/acdlite/recompose">https://github.com/acdlite/recompose</a></p>

<pre><code>const ColorBox = R.withState('color', 'setColor', 'ff0')(  
  ({color, setColor}) =&gt; (
    &lt;div style={{backgroundColor: `#${color}`, width: 80, height: 80}}
         onClick={() =&gt; setColor(color.slice(1) + color[0])} &gt;
    &lt;/div&gt;
  )
)
</code></pre>

<h2 id="reducer">reducerについて</h2>

<p>ES2015からのsyntax大変良い。 <br>
確かにImmutableを保証したくはなるが、私はImmutable.jsを使うのは、記述力の低下な対して、得られる保証が見合ってないのではと思う。 <br>
一方、ちゃんとImmutableなデータ構造を使わないとパフォーマンスが悪いのはその通りで。　ケースバイケース。</p>

<p>-- 追記</p>

<p>正直jsの仕様でなんとかしてほしい。 <br>
または、リストやオブジェクト周りのリテラルをOverloadできれば良い。</p>

<p>-- ここまで</p>

<h2 id="">他副作用の扱いついて</h2>

<p>saga middlewareがおすすめ</p>

<p>-- 要比較表</p>

<h2 id="">感想</h2>

<p>不満に思ったところを調べていくとだいたい既にtryがあった。 <br>
みんなjsという縛りの中で頑張っている。</p>

<p>flow楽しそうだが、もうjsでなくて良いのではってなる。 <br>
elm, purescriptや他altjsの今後にも期待。</p>]]></content:encoded></item><item><title><![CDATA[#12136 (SIGABRT on right-shift operation against long negative integer) - GHC #hasmoku]]></title><description><![CDATA[<p>Haskellもくもく会でのGHCへのコミットのシェア</p>

<script async class="speakerdeck-embed" data-id="aae39526621a419285b6e92925200c7a" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>]]></description><link>http://blog.nakaji.me/ghc-12136/</link><guid isPermaLink="false">cec31eba-1db9-4023-b308-f2c8cd65663c</guid><category><![CDATA[Haskell]]></category><category><![CDATA[GHC]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sat, 25 Mar 2017 06:01:03 GMT</pubDate><content:encoded><![CDATA[<p>Haskellもくもく会でのGHCへのコミットのシェア</p>

<script async class="speakerdeck-embed" data-id="aae39526621a419285b6e92925200c7a" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>]]></content:encoded></item><item><title><![CDATA[循環プログラミングに驚いた(repmin problem)]]></title><description><![CDATA[<p>GHC拡張RecursiveDoが何か知りたく、<a href="https://ocharles.org.uk/blog/posts/2014-12-09-recursive-do.html">https://ocharles.org.uk/blog/posts/2014-12-09-recursive-do.html</a> この記事を読んだ。</p>

<p>RecursiveDoに到達する以前に単に遅延評価に衝撃を受けたのでシェアさせていただきます。</p>

<hr>

<h2 id="repminproblem">repmin problem</h2>

<p>というもの。</p>

<p>何らかのtraversableなもの、例えば次のような木構造を、</p>

<pre><code>Tree 4 [Tree 6 [], Tree 2 []]  
</code></pre>

<p>木構造内の一番小さい値をつかって更新したい、</p>

<pre><code>Tree 2 [Tree 2 [], Tree 2 []]  
</code></pre>

<p>という問題。
（例えば各値を全体の割合にしたいとか）</p>

<p>これ普通に考えると、2回走査が必要。</p>

<p>しかし、「更新後のTreeと、最小の値を返す関数」を作ったとして、</p>

<pre><code>let (tree', minimum) = f tree minimum  
</code></pre>

<p>ということができてしまう。 <br>
という話題でした。</p>

<p>右辺に左辺で定義される<code>minimum</code>が出てきて、「なにこれ」となったが、</p>]]></description><link>http://blog.nakaji.me/circular-programming-1/</link><guid isPermaLink="false">8fb3d2cb-078c-4918-9dad-0155f1feae27</guid><category><![CDATA[Haskell]]></category><category><![CDATA[Programming]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Sat, 28 Jan 2017 03:24:00 GMT</pubDate><content:encoded><![CDATA[<p>GHC拡張RecursiveDoが何か知りたく、<a href="https://ocharles.org.uk/blog/posts/2014-12-09-recursive-do.html">https://ocharles.org.uk/blog/posts/2014-12-09-recursive-do.html</a> この記事を読んだ。</p>

<p>RecursiveDoに到達する以前に単に遅延評価に衝撃を受けたのでシェアさせていただきます。</p>

<hr>

<h2 id="repminproblem">repmin problem</h2>

<p>というもの。</p>

<p>何らかのtraversableなもの、例えば次のような木構造を、</p>

<pre><code>Tree 4 [Tree 6 [], Tree 2 []]  
</code></pre>

<p>木構造内の一番小さい値をつかって更新したい、</p>

<pre><code>Tree 2 [Tree 2 [], Tree 2 []]  
</code></pre>

<p>という問題。
（例えば各値を全体の割合にしたいとか）</p>

<p>これ普通に考えると、2回走査が必要。</p>

<p>しかし、「更新後のTreeと、最小の値を返す関数」を作ったとして、</p>

<pre><code>let (tree', minimum) = f tree minimum  
</code></pre>

<p>ということができてしまう。 <br>
という話題でした。</p>

<p>右辺に左辺で定義される<code>minimum</code>が出てきて、「なにこれ」となったが、遅延評価の言語なので、thunkとして扱うことができる。</p>

<p>（RecursiveDoは、例での評価したい値の取得にIOがある場合は？と言うものらしい）</p>

<p>言語の特性によって新たな物の考え方を得ることがたまにある。そのような時はとても楽しい。</p>]]></content:encoded></item><item><title><![CDATA[翻訳: The Architecture of Open Source Applications (Volume 2): The Glasgow Haskell Compiler]]></title><description><![CDATA[<p><em>この記事は<a href="http://www.aosabook.org/en/ghc.html">The Architecture of Open Source Applications (Volume 2): The Glasgow Haskell Compiler</a>の翻訳です。</em></p>

<hr>

<p><a href="http://www.aosabook.org/en/index.html"><img src="http://www.aosabook.org/images/titlebar2.jpg" alt="The Architecture of Open Source Applications (Volume 2)" title=""></a></p>

<h1 id="theglasgowhaskellcompiler">The Glasgow Haskell Compiler</h1>

<p><a href="http://www.aosabook.org/en/intro2.html#marlow-simon">Simon Marlow</a>と<a href="http://www.aosabook.org/en/intro2.html#peyton-jones-simon">Simon Peyton-Jones</a></p>

<p>Glasgow Haskell Compiler（GHC）は次のいくつかの目標と共に、1990年代の初めに英国政府によって学術研究プロジェクトの一環として設立されました。</p>

<ul>
<li>堅牢で移植性があり、高性能なコードを生成できるHaskellのコンパイラを自由に利用できるようにする</li>
<li>他の研究者が拡張・開発することができるモジュラー基盤を提供する</li>
<li>より良いコンパイラを設計・構築することができるように、現実世界のプログラムがどのように動作するかを学習する</li>
</ul>

<p>GHCは現在、20歳以上になり、 プロジェクト開始以降、継続的に活発に開発が行われています。今日では、GHCのリリースは数十万人にダウンロードされ、Haskellライブラリのオンラインリポジトリは3000以上のパッケージを持っており、多くの学部課程でHaskellを教えるために使用され、商業的にHaskellが使われる事例も増えてきています。</p>

<p>GHCのその生涯の中で、GHCにいくらかのコードを貢献した人は数百人いるものの、大抵は2人または3人のアクティブな開発者がいました。GHCのメインの開発者の私達の究極の目標はコーディングよりも学術的研究を行うことだが、GHCの開発を不可欠な前提条件と考えています。</p>]]></description><link>http://blog.nakaji.me/architecture-of-open-source-applications-volume-2-the-glasgow-haskell-compiler/</link><guid isPermaLink="false">26fae492-2b27-47ae-bfcd-8ba96fe9b90b</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Fri, 13 Jan 2017 11:06:39 GMT</pubDate><content:encoded><![CDATA[<p><em>この記事は<a href="http://www.aosabook.org/en/ghc.html">The Architecture of Open Source Applications (Volume 2): The Glasgow Haskell Compiler</a>の翻訳です。</em></p>

<hr>

<p><a href="http://www.aosabook.org/en/index.html"><img src="http://www.aosabook.org/images/titlebar2.jpg" alt="The Architecture of Open Source Applications (Volume 2)" title=""></a></p>

<h1 id="theglasgowhaskellcompiler">The Glasgow Haskell Compiler</h1>

<p><a href="http://www.aosabook.org/en/intro2.html#marlow-simon">Simon Marlow</a>と<a href="http://www.aosabook.org/en/intro2.html#peyton-jones-simon">Simon Peyton-Jones</a></p>

<p>Glasgow Haskell Compiler（GHC）は次のいくつかの目標と共に、1990年代の初めに英国政府によって学術研究プロジェクトの一環として設立されました。</p>

<ul>
<li>堅牢で移植性があり、高性能なコードを生成できるHaskellのコンパイラを自由に利用できるようにする</li>
<li>他の研究者が拡張・開発することができるモジュラー基盤を提供する</li>
<li>より良いコンパイラを設計・構築することができるように、現実世界のプログラムがどのように動作するかを学習する</li>
</ul>

<p>GHCは現在、20歳以上になり、 プロジェクト開始以降、継続的に活発に開発が行われています。今日では、GHCのリリースは数十万人にダウンロードされ、Haskellライブラリのオンラインリポジトリは3000以上のパッケージを持っており、多くの学部課程でHaskellを教えるために使用され、商業的にHaskellが使われる事例も増えてきています。</p>

<p>GHCのその生涯の中で、GHCにいくらかのコードを貢献した人は数百人いるものの、大抵は2人または3人のアクティブな開発者がいました。GHCのメインの開発者の私達の究極の目標はコーディングよりも学術的研究を行うことだが、GHCの開発を不可欠な前提条件と考えています。 研究成果物はGHCにフィードバックされるため、GHCはこれまでのアイデアを基にしたさらなる研究の基礎として使用することができます。さらに、それを用いて製造研究成果に大きな信頼を与えるため、GHCが非常に強力な製品であることが重要です。このように、GHCには最先端の研究のアイデアのが詰まっています。一方で、それがプロダクション利用で信頼できるようにすることにもかなり多くの労力を払っています。一見矛盾した2つのゴールに多くの場合葛藤がありますが、私たちは概ね研究目的とプロダクション利用の2つを満たすパスを見つけました。</p>

<p>この章では、GHCのアーキテクチャの概要をお伝えし、GHCで成功している一握りのキーアイデアに焦点を当てたいと思います（まだ成功していないものも幾つか）。以下のページを通して、私達が（一般的に言って）小さな開発チームで、どのようにして巨大なソフトウェアプロジェクトを20年以上に渡り自重により崩壊させることなく管理し続けられたのか、についてみなさんが知見を得られることを望んでいます。</p>

<h2 id="51haskell">5.1.　Haskellとは何ですか？</h2>

<p>Haskellとは、Haskell 2010が最新版の「Haskell Report」というドキュメントによって定義されている関数型プログラミング言語です [<a href="http://www.aosabook.org/en/bib2.html#haskell2010">Mar 10</a>]。Haskellは、関数型言語に興味を持つ学術研究コミュニティの数人のメンバーによって、彼らの調査研究の中心として用いることのできる共通言語の欠如の埋め合わせとして、1990年に創出されました。</p>

<p>諸プログラミング言語中、Haskellの下記2点の特徴が際立っています。</p>

<ul>
<li>それは<em>純関数(purely functional)</em>です。つまり、関数は副作用や変化するデータを持つことができません（入力（引数）のセットに対して関数は常に同じ結果を返します）。このモデルのコードについての推論をする上での利点は明らかですが(コードを書くことについても同様だと信じています)、入出力を純粋な関数の環境に結合することは重要な課題でした。幸いにも、<em>モナド</em>という形式のエレガントな解決策を発見されました。それは入出力を適切に純関数のコードに結合するだけではなく、新しい強力な抽象化をもたらしHaskellでのコーディングに革命を起こしました（そしてその後他の言語にも影響を与えた）。</li>
<li>それは<em>非正格(lazy)</em>です。これは言語の評価戦略を示しています。ほとんどの言語では、関数が呼び出される前に、関数の引数が評価される<em>正格(strict)な</em>評価を使用しているのに反して、Haskellでは関数に評価されていない引数が渡され、必要になり次第評価されます。</li>
</ul>

<p>Haskellはまた、<em>強い型付</em>を持っていて、<em>型推論を</em>サポートしています（これは型注釈がめったに必須にならないことを意味します）。</p>

<p>Haskellの完全な歴史に興味のある方は、こちらをお読みください [ <a href="http://www.aosabook.org/en/bib2.html#haskellhistory">HHPW07</a> ]。</p>

<h2 id="52highlevelstructure">5.2.　High-Level Structure</h2>

<p>最も上位のレベルにおいて、GHCは、3つの個別の塊に分割することができます。</p>

<ul>
<li>コンパイラ自体。これは、Haskellソースコードを実行可能なマシンコードに変換することを役割とする本質的なHaskellのプログラムです。</li>
<li>ブートライブラリ。GHCはコンパイラ自体が依存するライブラリを構成する為に、ブートライブラリと呼ばれるライブラリのセットを備えています。ソースツリーにこれらのライブラリを持つことは、GHCが自身をブートストラップできることを意味します。プリミティブな<code>Int</code>型のように、低レベルの機能を実装するため、これらのライブラリのいくつかは非常にしっかりとGHCに結合されています。Data.Mapのような他のライブラリはより高レベルであり、コンパイラに依存しません。</li>
<li>ランタイム・システム（RTS）。これは、ガベージコレクションやスレッドスケジューリング、プロファイリング、例外処理を含む、コンパイルされたHaskellコードの<em>実行</em>に関連するすべてのタスクを処理するC言語の大規模なライブラリです。RTSはすべてのコンパイルされたHaskellのプログラムにリンクされています。RTSはGHCにとりこまれた開発成果の重要な部分であり、そこでの設計上の決定は、並行性と並列処理の効率的なサポートなどのHaskellの強みに対していくつかの責任があります。RTSについては<a href="http://www.aosabook.org/en/ghc.html#s:rts">Section 5.5</a>でより詳細に説明します。</li>
</ul>

<p>実際にこれら3つの区分はGHCのソースツリーの3つのサブディレクトリーと正確に対応します（<code>compiler</code> と <code>libraries</code> , <code>rts</code>）。</p>

<p>ここでブートライブラリについての議論に多くの時間を費やすことはありません。なぜなら、それらはの大部分はアーキテクチャの観点から面白くないためです。すべての主要な設計上の決定は、コンパイラとランタイムシステムで具現化されているので、これらの二つのコンポーネントについての議論に、この章の残りを捧げます。</p>

<h3 id="codemetrics">Code Metrics</h3>

<p>我々が最後にGHCの行数を測定したのは1992年のこと（"The Glasgow Haskell compiler: a technical overview", JFIT technical conference digest, 1992）であり、そこからどのような変化があるのか見てみることは興味深いです。<a href="http://www.aosabook.org/en/ghc.html#f:lines">図5.1</a>は、 GHCのコードを主要なコンポーネントごとに分割した行数の内訳です。現在の結果と1992年のものを比較してみています。</p>

<figure id="f:lines">  

<table class=" table-condensed ">  
<thead>  
<tr>  
<th>Module</th>  
<th>行数(1992)</th>  
<th>行数(2011)</th>  
<th>増加率</th>  
</tr>  
</thead>  
<tbody>  
<tr>  
<td colspan="4"><i>Compiler</i></td>  
</tr>  
<tr>  
<td>Main</td>  
<td align="right">997</td>  
<td align="right">11,150</td>  
<td align="right">11.2</td>  
</tr>  
<tr>  
<td>Parser</td>  
<td align="right">1,055</td>  
<td align="right">4,098</td>  
<td align="right">3.9</td>  
</tr>  
<tr>  
<td>Renamer</td>  
<td align="right">2,828</td>  
<td align="right">4,630</td>  
<td align="right">1.6</td>  
</tr>  
<tr>  
<td>Type checking</td>  
<td align="right">3,352</td>  
<td align="right">24,097</td>  
<td align="right">7.2</td>  
</tr>  
<tr>  
<td>Desugaring</td>  
<td align="right">1,381</td>  
<td align="right">7,091</td>  
<td align="right">5.1</td>  
</tr>  
<tr>  
<td>Core transformations</td>  
<td align="right">1,631</td>  
<td align="right">9,480</td>  
<td align="right">5.8</td>  
</tr>  
<tr>  
<td>STG transformations</td>  
<td align="right">814</td>  
<td align="right">840</td>  
<td align="right">1</td>  
</tr>  
<tr>  
<td>Data-Parallel Haskell</td>  
<td align="right">—</td>  
<td align="right">3,718</td>  
<td align="right">—</td>  
</tr>  
<tr>  
<td>Code generation</td>  
<td align="right">2913</td>  
<td align="right">11,003</td>  
<td align="right">3.8</td>  
</tr>  
<tr>  
<td>Native code generation</td>  
<td align="right">—</td>  
<td align="right">14,138</td>  
<td align="right">—</td>  
</tr>  
<tr>  
<td>LLVM code generation</td>  
<td align="right">—</td>  
<td align="right">2,266</td>  
<td align="right">—</td>  
</tr>  
<tr>  
<td>GHCi</td>  
<td align="right">—</td>  
<td align="right">7,474</td>  
<td align="right">—</td>  
</tr>  
<tr>  
<td>Haskell abstract syntax</td>  
<td align="right">2,546</td>  
<td align="right">3,700</td>  
<td align="right">1.5</td>  
</tr>  
<tr>  
<td>Core language</td>  
<td align="right">1,075</td>  
<td align="right">4,798</td>  
<td align="right">4.5</td>  
</tr>  
<tr>  
<td>STG language</td>  
<td align="right">517</td>  
<td align="right">693</td>  
<td align="right">1.3</td>  
</tr>  
<tr>  
<td>C-- (was Abstract C)</td>  
<td align="right">1,416</td>  
<td align="right">7,591</td>  
<td align="right">5.4</td>  
</tr>  
<tr>  
<td>Identifier representations</td>  
<td align="right">1,831</td>  
<td align="right">3,120</td>  
<td align="right">1.7</td>  
</tr>  
<tr>  
<td>Type representations</td>  
<td align="right">1,628</td>  
<td align="right">3,808</td>  
<td align="right">2.3</td>  
</tr>  
<tr>  
<td>Prelude definitions</td>  
<td align="right">3,111</td>  
<td align="right">2,692</td>  
<td align="right">0.9</td>  
</tr>  
<tr>  
<td>Utilities</td>  
<td align="right">1,989</td>  
<td align="right">7,878</td>  
<td align="right">3.96</td>  
</tr>  
<tr>  
<td>Profiling</td>  
<td align="right">191</td>  
<td align="right">367</td>  
<td align="right">1.92</td>  
</tr>  
<tr>  
<td><b>Compiler Total</b></td>  
<td align="right"><b>28,275</b></td>  
<td align="right"><b>139,955</b></td>  
<td align="right"><b>4.9</b></td>  
</tr>  
<tr>  
<td colspan="4">  
<i>Runtime System<i></i></i></td>  
</tr>  
<tr>  
<td>All C and C-- code</td>  
<td align="right">43,865</td>  
<td align="right">48,450</td>  
<td align="right">1.10</td>  
</tr>  
</tbody>  
</table>  

<figcaption>図5.1：GHCの過去と現在のコードの行数</figcaption>  
</figure>

<p>これらの図にはいくつかの注目すべき側面があります。</p>

<ul>
<li>20年近くのコンパイラのノンストップな開発にもかかわらず、Haskelのコード行数は約28,000から約140,000と5倍程度にしか増加していません。私達は新しいコードを追加するとともに、コードベースを可能な限り新鮮な状態に維持できるよう、執拗にリファクタリングをしてきました。</li>
<li>幾つかの新しいコンポーネントがあるが、これらは約28,000行程度の新規の行のみを占めている。新しいコンポーネントの多くはコード生成に関するものです（各種プロセッサのネイティブコードジェネレータ、およびLLVMコードジェネレータ）。（旧"Low Level Virtual Machine"、LLVMプロジェクトには多くの異なるプロセッサをターゲットとする汎用コード・ジェネレータが含まれています。詳細については<a href="http://llvm.org/">http://llvm.org/</a>および、<em>"The Architecture of Open Source Applications"</em>第1巻のLLVMに関する章を参照してください。）また、対話型のインタプリタGHCiのためのインフラストラクチャについては7000行以上を追加しました。</li>
<li>単一のコンポーネントでの最大の増加はtype checkerであり、20,000以上の行が追加されています。これは、GHCを用いた最近の研究の多くは、新しい型システムの拡張になっていることを考えると驚くべきことではありません（例: GADTs [<a href="http://www.aosabook.org/en/bib2.html#gadts">PVWW06</a> ]やType Families[ <a href="http://www.aosabook.org/en/bib2.html#type-families">CKP05</a> ]）。</li>
<li><code>Main</code>コンポーネントには多くのコードが追加されましたが、これは部分的です。なぜなら、driverと呼ばれる3000行のPerlスクリプトだったものがHaskellで書き換えられ、適切なGHCに移されたためであり、また、複数のモジュールをコンパイルするためのサポートが追加されたことも一因です。</li>
<li>ランタイムシステムはわずかに成長しています。多くの新機能を積み上げて、より多くのプラットフォームに移植されたのにもかかわらず、10%程度大きくなったのみです。私たちは1997年辺りにそれを完全に書き直しました。</li>
<li>現在、GHCはGNU makeの約6,000行のコードからなる複雑なビルドシステムを持っています。それは、4回の完全な書き直しの上で成り立っています。この継続的な繰り返しはコードの量を削減しました。</li>
</ul>

<h3 id="thecompiler">The Compiler</h3>

<p>コンパイラは３つに分割することができます。</p>

<ul>
<li>複数のHaskellのソースファイルのコンパイルを担当している<em>compilation manager</em> 。コンパイルマネージャーの仕事は、異なるファイルをどの順序でコンパイルするか、 どのモジュールはコンパイルする必要が無いか（それの依存が最後のコンパイル以降変更されていないため）、を理解することです。</li>
<li>単一のHaskellソースファイルのコンパイルを処理する<em>Haskellのコンパイラ</em>（私たちはGHC内で<code>Hsc</code>と略しています）ご想像の通り、アクションのほとんどはここで行われます。<code>Hsc</code>の出力は選択されているバックエンドに依存します（アセンブリ、LLVMコード、またはバイトコード）。</li>
<li><code>Hsc</code>がHaskellコードをオブジェクトコードにコンパイルするのに必要な外部プログラムを一緒に構成する責任がある<em>pipeline</em> 例えば、Haskellのソースファイルは<code>Hsc</code> に流し込む前に、Cプリプロセッサで前処理が必要になる場合があります。 <code>Hsc</code>の出力は通常アセンブリファイルであり、これはオブジェクトファイルを作るためにアセンブラに流し込む必要があります。</li>
</ul>

<p>コンパイラはこれらの機能を実行するだけの単純さではありません。それ自体が、IDEや分析ツールなどのHaskellソースコードと共に動作する他のツールを構築するために使用できる大きなAPIを備えた <em>ライブラリ</em>です。</p>

<h3 id="compilinghaskellcode">Compiling Haskell Code</h3>

<p>ほとんどのコンパイラと同様に、Haskellのソースファイルのコンパイルは、連続したフェーズで進みます。各フェーズの出力は次の段階の入力になっています。各フェーズの全体像は<a href="http://www.aosabook.org/en/ghc.html#fig.ghc.pipeline">図5.2</a> に示されています。</p>

<figure id="fig.ghc.pipeline">  
<img src="http://www.aosabook.org/images/ghc/hscpipe2.png" alt="">
<figcaption>図5.2：he compiler phases</figcaption>  
</figure>

<h4 id="parsing">Parsing</h4>

<p>入力としてHaskellのソースファイルを受け取り抽象構文を出力する、伝統的な方法で構文解析を初めます。GHCでは抽象構文データ型<code>HsSyn</code>、はそれが含む識別子の型によってパラメーター化されます。つまり、抽象構文木はいくつかの識別子の型<code>t</code>のための<code>HsSyn t</code>型を持っています。 これは、同じタイプの抽象構文木を再利用しながら、プログラムがコンパイラのさまざまな段階を通過するように、識別子に多くの情報を追加することを可能にしています。</p>

<p>parserの出力は、識別子が<code>RdrName</code>と呼ばれる単純な文字列である抽象構文木です。したがって、parserによって生成された生成抽象構文は<code>HsSyn RdrName</code> 型を持ちます。</p>

<p>GHCは字句解析機と構文解析機それぞれの生成に<code>Alex</code>と<code>Happy</code>というツールを使います。これらはCでの <code>lex</code>と<code>yacc</code>に類似しています。</p>

<p>GHCのparserは純粋に機能的です。実際には、GHCのライブラリは、<code>parser</code>と呼ばれる純粋な関数を提供します。これは1つの<code>String</code>（と他の幾つか）を受取り、パースされた抽象構文またはエラーメッセージを返します。</p>

<h4 id="renaming">Renaming</h4>

<p>Renamingは、Haskellソースコード内のすべての識別子を完全修飾名に解決するプロセスです。同時に、スコープ外の識別子を特定し、エラーを適切に報告することができます。</p>

<p>Haskellでは別のモジュールからインポートした識別子を再度エクスポートすることが可能です。例えば、モジュール<code>A</code>で<code>f</code>と呼ばれる関数が定義さている場合に、モジュール<code>B</code>でモジュール<code>A</code>をインポートした上で再度<code>f</code> をエクスポートすることができます。ここで、モジュール<code>C</code>がモジュール<code>B</code>をインポートすると、<code>f</code>を<code>B.f</code>として参照できるが、<code>f</code>のオリジナルはモジュール<code>A</code>で定義されています。これは、名前空間操作の有用な形態です。ライブラリは内部的に好きなモジュール構造を使用することを意味しますが、内部モジュールから識別子を再エクスポートするいくつかのインターフェイスモジュールを介してクリーンなAPIを公開しています。</p>

<p>しかし、コンパイラはそれをすべて解決しないといけません。そのためにソースコード上の各名前がどのようなものに対応しているかを知っている必要があります。私たちは <em>entities</em>間できれいに区分しました。「それら自体」(例では<code>A.f</code> )、及び参照できるentitiesによる名前(例: <code>B.f</code>)。ソースコード中の任意の時点で、スコープ内のエンティティのセットがあり、それぞれは、1つまたは複数の異なる名前で知られています。renamerの仕事は、特定のエンティティを参照することによって、コンパイラのコードの内部表現での名前のそれぞれをリネームすることです。時々名前は、いくつかの異なるエンティティを参照することができます。それ自体ではエラーになりませんが、名前が実際に使用されている場合、renamerは曖昧性エラーのフラグを立て、プログラムをリジェクトします。</p>

<p>renamingは、Haskellの抽象構文（<code>HsSyn ,RdrName</code>）を入力とし、抽象構文（<code>HsSyn Name</code> ）を出力として生成します。ここで<code>Name</code>は特定のエンティティへの参照です。</p>

<p>名前の解決はrenamerの主な仕事ですが、それは他にも多すぎるタスクを実行します。 </p>

<ul>
<li>一緒に関数の方程式を収集し、引数の数が異なる場合は、エラーフラグを立てます。</li>
<li>演算子の結合性に応じて中置式を再配置します。</li>
<li>重複する宣言を見つける。</li>
<li>未使用の識別子へのワーニングを生成する。 </li>
<li>など他にも</li>
</ul>

<h4 id="typechecking">Type Checking</h4>

<p>想像されるように型チェックは、Haskellのプログラムの型が正しいことを確認するプロセスです。プログラムは型チェッカーを通過した場合、実行時にクラッシュしないことが保証されています。（ここでの「クラッシュ」という用語は"segmentation fault"のようなハードクラッシュを含むが、パッターンマッチングの失敗のような事は含まないという正式な定義があります。非クラッシュ保証は、外部関数インタフェースなどの特定の危険な言語機能を使用することによって破壊させることができます。）</p>

<p>型チェッカーに入力されるのは<code>HsSyn Name</code> （修飾名とHaskellソース）であり、出力は<code>HsSyn Id</code> です。<code>Id</code>は特別な情報、とりわけ<em>type</em> 、を持つ<code>Name</code>です。実際に、型チェッカーによって生成されたHaskellの構文は型情報で完全に修飾されています。 すべての識別子にそれの型が付加されていて、どの部分式の型を再構築するのにも十分な情報があります（これは、例えばIDEにとって便利です）。</p>

<p>実際問題として、Template Haskellの機能は実行時にコードを生成するため、型チェックと名前の変更が挟み込まれることがあります。</p>

<h4 id="desugaringandthecorelanguage">Desugaring, and the Core language</h4>

<p>Haskellは多くの異なる構文形式を含む、とても大きな言語です。これは人間にとって読み書きしやすいことを意図しています。 広い範囲の公文構造があり、プログラマが状況に応じて最も適切な構成を選択できる用、多大な柔軟性を与えています。しかし、この柔軟性は、同じコードを記述する場合、いくつかの方法があることがよくある事を意味します。例えば、<code>if</code>式は、<code>True</code>と<code>False</code>に分岐する<code>case</code>と同じ意味であり、リスト内包表記は<code>map</code> や <code>filter</code> 、<code>concat</code> の呼び出しに変換することができます。実際には、Haskell言語の定義は、これらを単純な構成物に変換することで、これらの構成物を定義します。このように別の構成物に変換できる構築物は、「糖衣構文（シンタックスシュガー）」と呼ばれています。</p>

<p>すべてのシンタックスシュガーが取り除かれている状態は、コンパイラにとって遥かに単純です。Haskellプログラムで動作する必要がある後続の最適化パスに対処する言語が小さくなるためです。デシュガーのプロセス、つまりすべてのシンタックスシュガーを取り除くプロセスは、フルのHaskellの構文を<code>Core</code>と呼ばれるはるかに小さい言語に変換することです。<code>Core</code>についての詳細は<a href="http://www.aosabook.org/en/ghc.html#s:core">後で</a> 述べます。</p>

<h4 id="optimisation">Optimisation</h4>

<p>今、プログラムは<code>Core</code>となっているので 、最適化のプロセスを初めます。GHCの大きな強みの一つは、抽象化レイヤーから離れて最適化することであり、この作業のすべてが<code>Core</code>レベルで発生します。 <code>Core</code>は小さな関数型言語であるが、最適化を表現するためのとてつもなく柔軟な中間物であり、正格性解析のような非常にハイレベルなものから、演算子強度低減のような非常にローレベルなものまでを範囲としています。</p>

<p>最適化パスのそれぞれが<code>Core</code>を受取り、<code>Core</code> を生成します。ここでの主なパスは<em>Simplifier</em>と呼ばれ 、これの仕事はcorrectness-preserving transformationsの大きな集まりを適用することで、より効率的なプログラムを生成することです。これらの変換のいくつかは、精査されている値が明らかである場合のデッドコードの除去やcase式の縮小など単純で明確であり、また、関数のインライン展開や書き換え規則の適用などもっと複雑な物もあります（<a href="http://www.aosabook.org/en/ghc.html#s:rules">後に</a>議論します ）。</p>

<p>単純化は通常他の６つある最適化パスの間に実行されます。それらが実際に実行される順序は、ユーザーが選択した最適化レベルに依存します。</p>

<h4 id="codegeneration">Code Generation</h4>

<p>一度<code>Core</code>プログラムが最適化されると、コード生成のプロセスが開始します。幾つかのadministrative passesの後、コードジェネレーションが開始します。 コードは2つのルートの打ち一つを取ります。対話型インタプリタによって実行される<em>バイトコード</em>に変換されるか、または最終的に機械コードに変換される<em>コードジェネレータ</em>に渡されます。</p>

<p>コードジェネレーターは最初に<code>Core</code>を<code>STG</code>と呼ばれる言語に変換します。これはコードジェネレータが必要とするより多くの情報を注釈したのみで、本質的には単に<code>Core</code>です。そして、 <code>STG</code>は、明示的なスタックを備えた低レベルの命令型言語である<code>Cmm</code>に翻訳されます 。ここから、コードは3つのルートのいずれかを取ります。</p>

<ul>
<li><strong>Native code generation</strong> ：GHCにはいくつかのプロセッサ・アーキテクチャのための簡単なネイティブコードジェネレータが含まれています。この経路は、高速であり、ほとんどの場合、合理的なコードを生成します。</li>
<li><strong>LLVM code generation</strong> ： <code>Cmm</code> はLLVMコードに変換され、LLVMコンパイラに渡されます。この経路はNative code generationよりも長い時間がかかるが、場合によっては著しくより良いコードを生成することができます。</li>
<li><strong>C code generation</strong> ：GHCは通常のCコードを生成することができます。このルートは、他の2つの経路よりも大幅に遅いコードを生成しますが、新しいプラットフォームへのGHCを移植するのに便利です。</li>
</ul>

<h2 id="53keydesignchoices">5.3.　 Key Design Choices</h2>

<p>このセクションでは、GHCで特に有効であった設計上の選択の一握りに焦点を当てます。</p>

<h3 id="theintermediatelanguage">The Intermediate Language</h3>

<figure id="fig.ghc.coresyntax">  

<table cellpadding="2">  
<tbody>  
<tr>  
<td colspan="3">Expressions</td>  
</tr>  
<tr>  
<td><i>t,e,u</i></td>  
<td>::=</td>  
<td><i>x</i></td>  
<td>Variables</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td><i>K</i></td>  
<td>Data constructors</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td><i>k</i></td>  
<td>Literals</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td>λ<i> x:σ.e</i> | <i>e u</i></td>  
<td>Value abstraction and application</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td>Λ<i> a:η.e</i> | <i>e φ</i></td>  
<td>Type abstraction and application</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td><b>let</b> <span style="text-decoration:overline"><i>x:τ = e</i></span> **in** <i>u</i></td>  
<td>Local bindings</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td><b>case</b> <i>e</i> <b>of</b> <span style="text-decoration:overline"><i>p</i>→<i>u</i></span></td>  
<td>Case expressions</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td>e ▷ γ</td>  
<td>Casts</td>  
</tr>  
<tr>  
<td></td>  
<td>|</td>  
<td>⌊ γ ⌋</td>  
<td>Coercions</td>  
</tr>  
<tr>  
<td><i>p</i></td>  
<td>::=</td>  
<td><i>K</i> <span style="text-decoration:overline"><i>c:η</i></span> <span style="text-decoration:overline"><i>x:τ</i></span></td>  
<td>Patterns</td>  
</tr>  
</tbody>  
</table>  

<figcaption>Figure 5.3: The syntax of `Core`</figcaption>  
</figure>

<p>静的型付け言語のコンパイラのための典型的な構造はこれです。プログラムが型をチェックされ、最適化される前に、いくつかの<em>型付けされていない</em>中間言語に変換されます。GHCは違います。それは<em>静的に型付けされた中間言語</em>を持っています。結論から言うと、この設計上の選択は、GHCの設計と開発に波及効果がありました。</p>

<p>GHCの中間言語は<code>Core</code>（実装のことを考える場合）またはSystem FC（理論を考える場合）と呼ばれています。その構文は<a href="http://www.aosabook.org/en/ghc.html#fig.ghc.coresyntax">。図5.3</a> で示されています。正確な詳細はここでは重要ではありません。興味のある読者はさらなる詳細を[<a href="http://www.aosabook.org/en/bib2.html#system-f">SCPD07</a>]で調べることができます。しかし、私たちの現在の目的のためには、以下の点が重要です。</p>

<ul>
<li><p>Haskellは非常に大規模なソースの言語です。その構文木を表すデータ型は、数百通りものコンストラクタを持っています。</p>

<p>これとは対照的に<code>Core</code>は 小さく、原則に基づいた、ラムダ計算です。それは非常にすくないいくつか文法の形式があり、まだ我々はへのHaskellのすべてを<code>Core</code> に翻訳することができます。</p></li>
<li><p>Haskellは<em>暗黙的に型付けされた</em>ソースの言語です。プログラムは、少しの方注釈を持っているかまたは持っていません。代わりに、型推論のアルゴリズムが、すべてのbinderと部分式の型を把握します。この型推論アルゴリズムは複雑であり、いくぶんその場しのぎであり、各々の実際のプログラミング言語が具現化する設計の妥協点を反映しています。</p>

<p>これとは対照的に<code>Core</code> <em>は明示的に型付けされた</em>言語です。各バインダは開示的な方を持ち、Every binder has an explicit type, and terms include explicit type abstractions and applications. <code>Core</code>は非常に単純で、プログラムが正しい型であることをチェックする高速な型チェックアルゴリズムを持っています。このアルゴリズムは完全に率直です。何のその場しのぎの妥協はありません。</p></li>
</ul>

<p>GHCのすべての解析と最適化パスは<code>Core</code> の上で動作します。これは素晴らしいです。なぜなら、 <code>Core</code>は最適化に対処するためのたったいくつかのケースのみを持っているような小さな言語だからです。 <code>Core</code>は小さいが、極めて表現力があります。結局のところ、System Fは、元は型付き計算の基礎計算として開発されました。新しい言語機能がソース言語に追加される際（これは常に起こります）、変更はフロントエンドのみに制限され、<code>Core</code>は変更されません。そしてコンパイラの殆どは変更されません。</p>

<p>しかし<code>Core</code>はなぜ型付けされているのでしょうか？結論、型推論エンジンがソース言語を受け入れた場合、そのプログラムは恐らく正しい型を持っていて、各最適化パスは恐らく型の正当性を維持しています。 <code>Core</code>高速な型チェックアルゴリズムを持てますが、なぜあなたはそれを実行したいのでしょうか？そのうえ、<code>Core</code>に型をつけることは重要なコストです。なぜなら各変換や最適化パスは正しい方のプログラムを生成する必要があり、そのすべての型注釈を生成する必要があることは、多くの場合些細なコストではないからです。</p>

<p>それにもかかわらず、いくつかの理由のために、明示的に型指定された中間言語を持つことは大きく優位性があります。</p>

<ul>
<li><p>実行中の<code>Core</code>の型チェッカー（我々は<code>Lint</code>と呼んでいる ）は、コンパイラ自体にとって非常に強力な整合性チェックとなります。仮に、あなたが誤って、整数値を関数として扱うコードを生成する最適化を書いてしまい、それを呼び出すところを想像してみてください。チャンスは、プログラムがセグメンテーションファルトするか、奇妙な方法で実行時に失敗することです。セグファルトをトレースしプログラムを壊している特定の最適化パスを見つけることは長い道のりです。</p>

<p>今度は代わりに、各最適化パスの後に<code>Lint</code>を実行していることを想像してみてください(<code>-dcore-lint</code> フラグを使うと実行される)。それは問題の最適化後の正格な一のエラーをすぐに報告します。What a blessing.</p>

<p>もちろん、「型の正しさ」は「正しいこと」と同じではありません： <code>Lint</code>はあなたが<code>(x*1)</code>を<em>x</em>にする代わりに1と最適化してしまった場合はエラーを通知しません。プログラムが <code>Lint</code> に合格した場合は、セグファルトなしで動作することが保証されています。 さらに実際には、型は正しいが意味的に間違っている最適化を書くことは驚くほど困難であることを私たちは発見しました。</p></li>
<li><p>Haskellのための型推論アルゴリズムは非常に大きく、非常に複雑です。<a href="http://www.aosabook.org/en/ghc.html#f:lines">図5.1</a>を見ると、型チェッカーがGHCの最大の単一コンポーネントであることが確認できます。大規模で複雑であることはエラーが発生しやすいことを意味します。しかし、 <code>Lint</code>は型推論エンジンに100％依存しないチェックとして機能します。型推論エンジンが、実際には型が正しくないプログラムを受け入れた場合、 <code>Lint</code>がそれを拒否します。ゆえに、 <code>Lint</code>は型推論エンジンの強力な監査役として機能します。</p></li>
<li><p><code>Core</code>の存在は、ソース言語の<em>設計</em>についての強力な健全性のチェックでもあることが判明しています。私達のユーザーは常々彼らの好きな機能の追加を提案します。時には、これらの機能は、明らかに「シンタックスシュガー」で、既に可能なことに対する便利な新しい構文です。しかし時々それらは奥深くなり、機能がどれほど遠くにあるのかを知るのは難しいかもしれません。</p>

<p><code>Core</code>は私たちにそのような機能を評価するための正確な方法を提供します。機能を容易に<code>Core</code>に翻訳できる場合は、本質的な新規性はないと私達を安心させます。新しい機能はシンタックスシュガーのようです。一方、<code>core</code>に拡張が必要な場合は、もっともっと慎重に考えます。</p></li>
</ul>

<p>実際に<code>Core</code>は信じられないぐらいステイブルでいます。20年の間で、我々はたった1つの新しい主要な機能を<code>core</code>に追加しました（具体的には、暗黙の型変換およびそれらに関連するキャスト）。同期間、ソース言語は莫大に進化してきました。私たちはこの安定性を私達の優れた才気によるものではないとしていて、<code>Core</code>が基礎数学に直接結びついているという事実に起因しています。bravo Girard!</p>

<h3 id="typecheckingthesourcelanguage">Type Checking the Source Language</h3>

<p>興味深い設計上の決定の1つは、型検査は脱糖の前後どちらに行われるべきかどうかです。トレードオフは次のとおりです。</p>

<ul>
<li>脱糖前の型チェックは、Haskellの非常に大規模な構文を直接扱う必要があるということを意味し、型チェッカーが考慮すべきケースがたくさんあります。仮に、最初に（型がない版の）<code>Core</code>に脱糖した場合、型チェッカーがはるかに小さくなることが期待されます。</li>
<li>一方、脱糖後の型チェックは重要な新たな責務を発生させます。脱糖はプログラムがそれらのプログラムの方が正しいかどうかに影響しません。結局、脱糖は意図的に情報量を落としていることを意味します。これはおそらく95％の場合に問題ないが、ここに<em>何かしら</em>問題がある場合は、<code>Core</code>の設計においていくつかの余分な情報を保持するようにいくつかの妥協を強いるでしょう。</li>
<li>最も深刻なこととして、脱糖されたプログラムの型チェックは元のプログラムのテキストに対してエラーを報告するのがはるかに困難になり、そして（ときには精巧な）脱糖されたバージョンではない。</li>
</ul>

<p>殆どのコンパイラが脱糖後に型チェックを行います。しかしGHCにおいて、私たちは反対の選択をしました。私たちはHaskellの完全な構文に対して型チェックをします。そしてその結果を脱糖します。これは、新しい構文構造を追加する際に、複雑になるかもしれないように聞こえますが（フランス語学校に続いて）、私たちはそれを簡単にできるように型推論エンジンを簡単に構成しました。型推論は、次の2つの部分に分かれています。</p>

<ol>
<li>制約の生成：構文木を探索し、型制約のコレクションを生成します。このステップはHaskellの完全な構文を扱うが、それは非常に簡単コードであり、新しいケースを追加するのは簡単です。  </li>
<li>制約の解決：集められた制約を解決します。これは型推論エンジンの巧妙な部分ですが、これはソース言語のシンタックスから独立していて、言語が大きくても小さくても同じものです。</li>
</ol>

<p>概して、脱糖前の型チェックという設計は大きな勝利であるということが判明しました。確かに、それは型チェッカーへのコードの追加を必要としますが、<em>単純な</em>コードです。これは、2つの相反した役割を同じデータ型に与えることを回避し、型推論エンジンをそれほど複雑ではなくし、変更しやすくしています。さらには、GHCのタイプエラーのメッセージはかなり良いです。</p>

<h3 id="nosymboltable">No Symbol Table</h3>

<p>コンパイラは通常<em>シンボルテーブル</em>として知られる1つ以上のデータ構造を持っています。これはシンボル(変数など)からの、それの型や、それがどこで定義されているかなどの情報へのマッピングです。</p>

<p>GHCでは、非常に控えめにシンボルテーブルを使用します（主にrenamerと型チェッカー内で）。可能な限り、我々は代替の戦略を使用します。変数はそれ自体に関するすべての情報を<em>含む</em>データ構造です。実際、変数のデータ構造をトラバースすることによって、大量の情報に到達することができます。 変数からその型を見ることができます。型コンストラクタはデータコンストラクタを含み、型コンストラクタ自体にも型があります。たとえば、GHCのデータ型（大幅に簡略化している）を次に示します。</p>

<pre><code>  data Id      = MkId Name Type
  data Type    = TyConApp TyCon [Type]
               | ....
  data TyCon   = AlgTyCon Name [DataCon]
               | ...
  data DataCon = MkDataCon Name Type ...
</code></pre>

<p><code>Id</code> はその<code>Type</code> を含んでいます。<code>Type</code>はいくつかの引数を適用されるかもしれません（<code>Maybe Int</code>等）。そのような場合は <code>TyCon</code> を含みます。<code>TyCon</code> は代数データ型とすることができます。その場合にはデータコンストラクタのリストを含みます。各<code>DataCon</code>は、その<code>Type</code>を含み、もちろん <code>TyCon</code> にも同じことがいえます。等など。構造全体が高度に相互接続されています。例えば、 <code>TyCon</code>には、<code>TyCon</code>を含む<code>Type</code>を含む<code>DataCon</code>が含まれています。</p>

<p>このアプローチにはいくつかの利点と欠点があります。</p>

<ul>
<li>シンボルテーブル内のルックアップを必要とする多くのクエリは、シンプルなフィールドアクセスに削減でき、これは効率化やコードのクリーンさのために最適です。</li>
<li>余分なシンボルテーブルを持ち歩く必要がなく、抽象構文木にはすでに、すべての情報が含まれています。</li>
<li>スペースのオーバーヘッドが優れています。同じ変数のインスタンスは同じデータ構造を共有し、テーブルのために必要なスペースはありません。</li>
<li>変数に関連付けられた情報を<em>変更</em>する必要がある場合のみ、困難が生じます。シンボルテーブルが優位性を持っているところです。シンボルテーブルのエントリを変更するだけですみます。GHCでは、抽象構文木を横断し、すべての古い変数のインスタンスを新しいものに変更する必要があります。各変数に関するある種の最適化関連の情報を更新する必要があるので、実際に、単純化はこれを定期的に行います。</li>
</ul>

<p>設計のこの側面は、変化がほとんど不可能なほど基本的なところなので、シンボルテーブルを使用することが、全体的に良いか悪いかを知ることは難しいです。それでも、シンボルテーブルを回避することは純関数の背景においては自然な選択なので、このアプローチがHaskellのために良い選択である可能性は高いようです。</p>

<h3 id="intermoduleoptimisation">Inter-Module Optimisation</h3>

<p>関数型言語は、小さな定義を書くことをプログラマに奨励します。例えば、これは標準ライブラリでの<code>&amp;&amp;</code>の定義です。</p>

<pre><code>(&amp;&amp;) :: Bool -&gt; Bool -&gt; Bool
True &amp;&amp; True = True  
_    &amp;&amp; _    = False  
</code></pre>

<p>このような関数を使用する際に毎回、実際に関数呼び出しが行われているとしたら、効率はひどく悪くなります。一つの解決策は、コンパイラが特定の関数を特別に扱うようにすることです。 別の解決策は、プリプロセッサを用いて、「呼び出し」を展開されたインラインコードに置き換えることです。これらのソリューションのすべては、いずれかの方法で不満足です。特に後者の解決策は非常に明白です。 「関数をインライン化」するということは、適切にそのパラメータをインスタンス化し、関数呼び出しを関数の内容に置き換えるということを意味します。</p>

<p>GHCでは、このアプローチを体系的に採用しています[<a href="http://www.aosabook.org/en/bib2.html#inlining">PM02を</a> ]。事実上、コンパイラに何も内蔵されていません。その代わりに、ライブラリ内でできるだけ多くを定義し、オーバーヘッドを排除するために積極的なインライン化を使用します。これは、 <em>プログラマは、GHC付属のライブラリと同じように、自身のライブラリもインライン化され最適化される用に定義できる</em> ことを意味します。</p>

<p>その結果として、GHCはcross-module(実際にはcross-packageも同様に)のインライン化ができる必要があります。アイディアは単純です。</p>

<ul>
<li>Haskellのモジュール<code>Lib.hs</code> をコンパイルする際、GHCは、オブジェクトコードを<code>Lib.o</code>に、「インタフェース・ファイル」を <code>Lib.hi</code> に生成します。このインタフェースファイルには、<code>Lib</code>からエクスポートされるすべての関数に関する情報が含まれていて、それにはその種類と、十分に小さな関数についてはそれらの定義、の両方を含んでいます。</li>
<li>モジュール<code>Client.hs</code>をコンパイルするときには<code>Lib</code>をインポートし、GHCはインタフェース<code>Lib.hi</code> を読み取ります。そして<code>Client</code> が<code>Lib</code> で定義された<code>Lib.f</code>を呼び出すのであれば、GHCは<code>Lib.f</code> をインライン化するために<code>Lib.hi</code>内の情報を使うことができます。</li>
</ul>

<p>デフォルトでは、GHCは関数が「小さい」場合にのみ、インタフェースファイル内に関数の定義を載せます（このサイズの閾値を制御するためのフラグがあります）。しかし、サイズに関係なく、呼び出し側で、積極的な定義のインライン化をする用にGHCに指示するための、INLINEプラグマをサポートしています。</p>

<pre><code>foo :: Int -&gt; Int  
{-# INLINE foo #-}
foo x = &lt;some big expression&gt;  
</code></pre>

<p>クロスモジュールのインライン化は、超効率的なライブラリを定義するための必要不可欠ですが、それはコストが付属していません。作者がライブラリをアップグレードする場合、<code>Client.o</code>を新しい<code>Lib.o</code>と再リンクするだけでは十分ではありません。なぜなら、<code>Client.o</code>は古い<code>Lib.hs</code>のインラインフラグメントを含んでいて、これは新しいものと互換性がないかもしれないからです。言い換えると、<code>Lib.o</code>のABI（Application Binary Interface）が、それのクライアントの再コンパイルが必要なように、変更されたということです。</p>

<p>実際に、fixedでpredictableなABIのコードを生成するためにコンパイルする唯一の方法は、ABIがクロスモジュール最適化を無効にすることであり、これはABIの互換性のために支払うのには、一般的に言って高すぎるコストです。GHCで作業するユーザーは、通常、スタック全体のソースコードを用意してますので、再コンパイルは通常は問題ありません（また、後に説明するように、パッケージシステムは、この作業モードを中心に設計されています）。しかし、再コンパイルが現実的ではないシチュエーションもあります。例えば、OSのディストリビューション内のライブラリに対してバグ修正を配布する場合などです。将来的には、私たちは、クロスモジュール最適化を可能にしつつ、ABIの互換性を保つことを可能にする解決策を見つけられることを願っています。</p>

<h2 id="54extensibility">5.4.　Extensibility</h2>

<p>プロジェクトの生死が、その拡張性の有無によって決まるというのは、よくあるケースです。拡張可能でないモノリシックなソフトウェアは、すべてのことができ、それを正しく行うことができる必要があります。一方で拡張可能なソフトウェアは、すべての必要な機能をすぐに使える状態で提供していなくても、役に立つ土台となりえます。</p>

<p>オープンソースプロジェクトは、もちろん定義によっては拡張可能です。つまり誰でもコードを取得し、自分で機能を追加できるという点です。 コードを取ると、自分自身の機能を追加することができ、誰に、定義によりコースの拡張可能です。しかし、他の誰かによってメンテナンスされているオープンソースコードを変更するというのは、ハイオーバーヘッドなアプローチと言うだけではなく、あなたの拡張機能を他に人に共有する助けとなっていません。したがって、成功したプロジェクトは、コアコードの変更を伴わない、拡張性の形態を提供する傾向があり、GHCもこの点で例外ではありません。</p>

<h3 id="userdefinedrewriterules">User-Defined Rewrite Rules</h3>

<p>GHCのコアは、いくつかのsemantics-preserving transformationをそれぞれ実行する（<code>Core</code>から<code>Core</code>に）、最適化パスの長いシーケンスである。しかく、ライブラリの作者は、多くの場合、いくつかの非自明な、それ自身のドメイン固有の変換を持つ関数を定義します。それはGHCからは予測できません。そこで、GHCはライブラリ作者に、最適化中にプログラムを書き換えるのに使用される<em>rewrite rules</em>を定義できるようにしました[ <a href="http://www.aosabook.org/en/bib2.html#playing-by-the-rules">PTH01</a> ]。このように、プログラマは、実際には、ドメイン固有の最適化とともに、GHCを拡張することができます。</p>

<p>一例として、<code>foldr/build</code> のルールは次のような式となっています。</p>

<pre><code>{-# RULES "fold/build"    
    forall k z (g::forall b. (a-&gt;b-&gt;b) -&gt; b -&gt; b) . 
       foldr k z (build g) = g k z
 #-}
</code></pre>

<p>すべてのルールはプラグまであり、<code>{-# RULES</code> によって開始されます。このルールは、GHCが式<code>(foldr k z (build g))</code>を見つけたときは、いつでも、<code>(g k z)</code>と書き換えるように言っています。この変換は、semantics-preservingですが、これについて論じている研究論文を取るので[<a href="http://www.aosabook.org/en/bib2.html#gill-short-cut">GLP93</a>]、GHCがそれを自動的に適用するチャンスはありません。他のルールや幾つかのINKINEプラグマの一握りと共に、GHCはlist-transforming機能を融合することができます。例えば、<code>(map f (map g xs))</code>中の2つのループは一つに融合されます。</p>

<p>書き換え規則は、シンプルで使いやすいが、それらは非常に強力な拡張機構であることが証明されています。10年前に我々が最初にGHCにこの機能を導入したとき、我々はそれが時折便利な設備になることを期待していました。しかし、実際には、その効率性が書き換え規則に決定的に依存している、多くのライブラリで便利なものとなった。例えば、GHC自身の<code>base</code>ライブラリは、100を超えるルールを含み、普及している<code>vector</code>ライブラリは数十を使用しています。</p>

<h3 id="compilerplugins">Compiler Plugins</h3>

<p>コンパイラが拡張性を提供できる為の一つの方法は、プログラマがコンパイラのパイプラインに直接挿入されるパスを記述できるようにすることです。このようなパスは多くの場合、「プラグイン」と呼ばれています。GHCは、次のような方法でプラグインをサポートしています。</p>

<ul>
<li>プログラマは、モジュール内に<code>Core</code>から<code>Core</code>へのパスを通常のHaskellの関数として書きます。例えば<code>P.hs</code>。そしてオブジェクトコードにコンパイルします。</li>
<li>いくつかのモジュールをコンパイルするとき、プログラマは、<code>-plugin P</code>コマンドラインフラグを使用しています 。（代わりに、モジュールの先頭でプラグマのフラグで指定することもできます）</li>
<li>GHCはを<code>P.o</code>を検索し、実行されているGHCバイナリに動的にリンクして、パイプライン内の適切な時点でそれを呼び出します。</li>
</ul>

<p>しかし、「パイプライン内の適切なポイント」とはどこですか？GHCはそれを知らないので、プラグインがその決定を行うことができます。これやその他の事項の結果として、プラグインが提供しなければならないAPIは、単一<code>Core</code>への<code>Core</code>関数よりも少し複雑であるが、そこまで多くはありません。</p>

<p>プラグインは時に、補助的なプラグイン固有のデータを必要とするか、または生成します。例えば、プラグインがモジュールがコンパイルされる際に関数ないで何らかの解析を行うとし（ <code>M.hs</code> とする）、その情報をインターフェースファイル<code>M.hi</code>ないに置きたいとします。そうすると、プラグインは、<code>M</code> をインポートするモジュールのコンパイル時に、その情報へアクセスできます。GHCはこれをサポートするアノテーションの仕組みを提供しています。</p>

<p>GHCにとって、プラグインと注釈は比較的新しいものです。これらは、GHC内部のデータ構造を扱うため、書き換えルールよりも高い壁を持っているが、当然プラグインはより多くのことができます。それらがどのぐらい広く使われるかはまだわかっていません。</p>

<h3 id="ghcasalibrarytheghcapi">GHC as a Library: The GHC API</h3>

<p>GHCの当初の目標の一つは、他の人がその上に構築することができる<em>モジュール式</em>の基盤であることでした。他の人達による研究プロジェクトの基礎として利用できるように、我々はGHCのコードが、わかりやすく、良くドキュメント化されていることを望みます。我々は、人々が、自身の変更をGHCに加えたり、実験的な新機能や最適化を加えうことを望んでいる想像しています。確かに、このような例がいくつかありました。例えば、LispをフロントエンドとしたGHCのバージョンや、Javaのコードを生成するGHCのバージョンが存在し、 両方の開発はGHCチームへのコンタクトは殆ど又は全く無く、完全に個別に行われました。</p>

<p>しかしながら、GHCの修正バージョンを生成することは、GHCのコードが再利用できる方法のほんの一部を表します。Haskell言語の人気が成長してきたように、Haskellのソースコードに通じているツールやインフラへのニーズが高まってきた。そしてもちろんのGHCは、これらのツールを構築するために必要な多くの機能が含まれています（Haskellのパーサ、抽象構文、型をようにチェッカーなど）。</p>

<p>これを念頭において、私たちはGHCに簡単な変更をしました。モノリシックなプログラムとしてGHCを構築するよりも、むしろ、GHCを<em>ライブラリ</em>としてビルドし、実行可能なGHCを作るために小さな<em>Main</em> モジュールとリンクしています。ライブラリ形式で提供されるため、ユーザーは自身のプログラムからそれを呼び出すことができます。同時に、私たちはクライアントにGHCの機能を公開するためのAPIを構築しました。APIは、GHCバッチコンパイラとGHCiのインタラクティブな環境を実装するために十分な機能を提供しますが、それはまた、そのようなパーサとタイプチェッカーなどの個々のパスへのアクセスを提供し、これらのパスによって生成されたデータ構造を検査することを可能にします。この変更は、GHCのAPIを使用して構築された次のようなツールの広い範囲への向上を与えています：</p>

<ul>
<li>文書化ツール、 <a href="http://www.haskell.org/haddock/">Haddock</a>、これはHaskellのソースコードを読み取り、HTMLドキュメントを生成します。</li>
<li>追加機能を持つ新しいバージョンのGHCiのフロントエンド（例えば、 <a href="http://hackage.haskell.org/package/ghci-haskeline">ghci-haskeline</a>）、その後GHCにマージバックされました。</li>
<li>Haskellのソースコードでの高度なナビゲーションを提供するのIDE。例えば、 <a href="http://hackage.haskell.org/package/leksah">Leksah</a> 。</li>
<li><a href="http://hackage.haskell.org/package/hint">hint</a> 、Haskellのソースコードのon-the-flyでの評価のためのシンプルなAPI。</li>
</ul>

<h3 id="thepackagesystem">The Package System</h3>

<p>パッケージシステムは、近年のHaskell言語の利用の成長における重要な要因となっています。その主な目的は、Haskellのプログラマはお互いにコードを共有できるようにすることであり、それは拡張性の重要な側面である。パッケージシステムは、GHC自体を超えて共有コードベースを拡張します。</p>

<p>パッケージシステムは、コードの共有を簡単にするインフラストラクチャのさまざまな部分を体現しています。パッケージシステムをイネーブラーとして使用することで、コミュニティは共有コードを大量に構築しています。Haskellプログラマーは、単一のソースからのライブラリに頼るのではなく、コミュニティ全体が開発したライブラリを利用しています。このモデルは、他の言語でもうまく働いています。 例えばPerl用のCPAN。 Haskellが主にインタプリタで実行されるのではなくコンパイルされる言語であることはやや異なる一連の課題を提示しますが。</p>

<p>基本的には、パッケージシステムは、ユーザが他の人によって書かれたHaskellコードのライブラリを管理し、独自のプログラムやライブラリでそれらを使用できるようにします。Haskellのライブラリのインストールは、単一のコマンドを打つだけで簡単です。例えば。</p>

<pre><code>$ cabal install zlib
</code></pre>

<p>これは<code>zlib</code>の為のコードを<a href="http://hackage.haskell.org">http://hackage.haskell.org</a>からダウンロードし、GHCを使いそれをコンパイルし、コンパイルされたコードをあなたのシステム上にインストールし（例えば、Unixシステムではあなたのホームディレクトリ）、GHCでインストールを登録します。さらに<code>zlib</code>がまだインストールされていない何らかのパッケージに依存しているのであれば、それらも<code>zlib</code> のインストールの前に、自動的にダウンロード、コンパイル、インストールされます。それは、他の人が共有したHaskellコードライブラリを動作させるすさまじくスムーズな方法です。</p>

<p>パッケージシステムは、１つ目のみ厳密にGHCプロジェクトの一部である、4つのコンポーネントで構成されています。</p>

<ul>
<li>あなたのシステムにインストールされているパッケージに関する情報についての単純なリポジトリ、を管理する<em>パッケージデータベース</em>。GHCは起動時にそれを参照し、どのパッケージが有効なのか、それはどこにあるのか、を知ります。</li>
<li><code>Cabal</code>と呼ばれるライブラリ（Common Architecture for Building Applications and Libraries） 。これは各々のパッケージをビルド・インストール・登録するための機能を実装します。</li>
<li><a href="http://hackage.haskell.org">http://hackage.haskell.org</a>のあるウェブサイト。これはユーザによって書かれアップロードされたパッケージをホストします。ウェブサイトはパッケージのドキュメントを自動生成し、オンラインで閲覧できます。執筆時点では、Hackageは3000以上のパッケージをホストしています。これらは、データベースライブラリ、Webフレームワーク、GUIツールキット、データ構造、およびネットワーキングなどの機能をカバーしています。</li>
<li>Hackageのウェブサイトと<code>Cabal</code>ライブラリを結びつけるツール<code>cabal</code>。それは、正しい順序で、Hackageからパッケージをダウンロードし、その依存関係を解決し、ビルド、インストールを行います。新しいパッケージもまた、コマンドラインから<code>cabal</code>を使用してHackageにアップロードすることができます。</li>
</ul>

<p>これらのコンポーネントは、HaskellのコミュニティとGHCチームのメンバーが数年にわたって開発してきました。ともにオープンソース開発モデルに完璧にフィットシステムを作ります。コードを共有するか、他の人が共有しているコードを使用することに何も障壁はありません（当然、関連するライセンスを尊重している限り）。あなたは、ほんの数秒でHackageから他の誰かが書いたパッケージを見つけ出し、それを使うことができます。</p>

<p>Hackageは成功していて、残る問題は現在の規模になったことによるものです。例えば、ユーザーは４つの異なるデータベースフレームワークから、選択をすることに難しさを感じています。進行中の開発は、コミュニティを活用しこれらの問題を解決することを目的としています。例えば、ユーザーがパッケージについてコメントや投票をできるようにし、最も最適で人気のパッケージを見つけられるようにします。さらに、ユーザーからビルドの成否に関する情報を収集し、結果をレポートすることで、メンテナンスされていないパッケージや問題のあるパッケージを避けることを可能にします。</p>

<h2 id="55theruntimesystem">5.5. The Runtime System</h2>

<p>ランタイムシステムは主にCのライブラリで、すべてのHaskellのプログラムにリンクされています。それはコンパイルされたHaskellのコードを実行するために必要なサポートインフラストラクチャを提供します。それは次の主要コンポーネントを含みます。</p>

<ul>
<li>メモリ管理。並列、世代別、ガベージコレクタを含みます。</li>
<li>スレッドの管理とスケジューリング。</li>
<li>GHCによって提供される基本操作。</li>
<li>GHCiのためのバイトコードインタプリタと動的リンカ。</li>
</ul>

<p>この節の残りの部分は、2つに分割されています。 前半は、RTSの幾つかのデザイン的な面について終点を当ます。それが成功しうまく機能することに役立ってきたと考えている面です。後半は、実践的なコーディングとインフラについて話します。これはかなり敵対的なプログラミング環境に対処するために、RTS内で作り上げられたものです。</p>

<h3 id="keydesigndecisions">Key Design Decisions</h3>

<p>このセクションでは、特に成功していると考えているRTSにおける設計上の決定のうちの2つを説明します。</p>

<h4 id="theblocklayer">The Block Layer</h4>

<p>ガベージコレクタは<em>block layer</em>の上に構築されています。それはブロック単位でメモリを管理します。1ブロックは4KBの倍数です。ブロック層は、非常にシンプルなAPIを持っています。</p>

<pre><code>typedef struct bdescr_ {  
    void *               start;
    struct bdescr_ *     link;
    struct generation_ * gen;   // generation
    // .. various other fields
} bdescr;

bdescr * allocGroup (int n);  
void     freeGroup  (bdescr *p);  
bdescr * Bdescr     (void *p);  // a macro  
</code></pre>

<p>これは、メモリを割り当て、割り当て解除のために、ガベージコレクタによって使用される唯一のAPIです。メモリのブロックは<code>allocGroup</code>で割り当てられ、<code>freeGroup</code> で解放されます。すべてのブロックは、<em>block describer</em>とよばれる、それに関連付けられた小さな構造体を持ちます（<code>bdescr</code>）。<code>Bdescr(p)</code>の操作は任意のアドレス<code>p</code>に関連付けられたblock descriptorを返します。これは<code>p</code> の値に基づく純粋なアドレス計算であり、少量の演算とビット操作命令にコンパイルされます。</p>

<p>ブロックは<code>bdescr</code> 内の<code>link</code>のフィールドを使用してチェーンにリンクすることができ、これがこのテクニックの新のパワーです。ガベージコレクタは、 <em>世代</em>など、幾つかの個別のメモリの領域を監視する必要があります。そして、それらの領域は時間とともに拡大・縮小することがあります。リンクされたブロックのリストとしてメモリ領域を表すことによって、GCは、多数の可変サイズのメモリ領域をフラットなメモリ空間に割り当てる難しさから開放されます。</p>

<p>ブロック層の実装は、Cの<code>malloc()/free()</code> APIからよく知られているテクニックを使用しています。それは様々なサイズの空きブロックのリストを維持し、空き領域を合体します。<code>freeGroup()</code>と<code>allocGroup()</code>の操作は、<em>O(1)</em>であるように慎重に設計されています。</p>

<p>この設計の1つの主要な利点は、OSからのサポートはほんの少ししか必要なく、それゆえに移植性がとても高くなることです。ブロック層は、1 MB単位でメモリを割り当て、1 MB境界に合わせて配置する必要があります。一般的なOSのどれもがこの機能を直接提供するわけではありませんが、提供する機能の点ではそれほど難しいことはありません。GHCは、OSによって使用されるアドレス空間レイアウトの特定の詳細に依存せず、共有ライブラリやオペレーティングシステムのスレッドなど、アドレス空間の他のユーザと平和的に共存するという利点があります。</p>

<p>連続したメモリではなく、ブロックのチェーンを管理する点について、ブロック層には少しの複雑なコストがかかります。しかし、我々はこのコストは、フレキシビリティとポータビリティについて、見合う以上であることを見出しました。 例えば、ブロック層は並列GCを特に単純なアルゴリズムで実装することを可能にしました[<a href="http://www.aosabook.org/en/bib2.html#parallel-gc">MHJP08</a>]。</p>

<h4 id="lightweightthreadsandparallelism">Lightweight Threads and Parallelism</h4>

<p>並行性は、特に多数の外部エージェントと同時に対話する必要のあるWebサーバーのようなアプリケーションを構築するために、非常に重要なプログラミングの抽象概念だと考えています。並行性が重要な抽象概念なのであれば、プログラマがそれを避けるほど高価であってはいけません。またはプログラマがそのコストを償却できるほど精巧な作りでないといけません。私たちは並行性は、正常に動作し、あなたが小さなタスクのためにスレッドをフォークすることを心配しなくても良いべきだと信じています。</p>

<p>すべてのオペレーティングシステムは完璧に正常に動作するスレッドを提供しているが、問題は、それらがあまりにも高価であるということです。典型的なOSが数千のスレッドを扱うことで努力しているのに対し、私たちは100万からのスレッドを扱いたいです。</p>

<p>Green Threads（または軽量スレッド、ユーザー空間スレッドとして知られる）は、OSスレッドのオーバーヘッドを回避するための周知の技術ですアイディアは、スレッドをオペレーティングシステムによってではなく、プログラム自体、またはライブラリ（私たちの場合は、RTS）によって管理させるというものです。オペレーティングシステムへのトラップが少なくて済むため、ユーザー空間のスレッドを管理するほうが安価です。</p>

<p>GHC RTSでは、このアイデアをフル活用します。スレッドが、追加の状態をほとんど保存する必要のない<em>安全点</em>にあるときにのみコンテキストスイッチが発生します。正確なGCを使用するので、スレッドのスタックは必要に応じて移動、拡張、縮小することができます。これをOSスレッドと比較すると、OSスレッドはすべてのコンテキストスイッチがプロセッサの状態全体を保存しなければならず、スタックが動かせないので、スレッドごとに大きなアドレス空間を予約する必要があります。</p>

<p>グリーンスレッドはOSスレッドよりもはるかに、より効率的な可能性があります、その上でなぜOSスレッドを使いたい人がいるんのでしょうか？それは3つの主要な問題にたどり着きます。</p>

<ul>
<li>ブロッキングと外部呼び出し。スレッドは、システム内の他のすべてのスレッドをブロックすることなく、ブロックするOS APIまたは外部ライブラリを呼び出すことができます。</li>
<li>並列処理。システム上に複数のプロセッサコアがある場合、スレッドは自動的に並列に実行される必要があります。</li>
<li>一部の外部ライブラリ（特にOpenGLといくつかのGUIライブラリ）は、スレッドローカルな状態を使用しているため、毎回同じOSスレッドから呼び出されなければならないAPIを持っています。</li>
</ul>

<p>それらのすべてをグリーンスレッドで手配するのは困難なことがわかりました。それにもかかわらず、我々はGHCをグリーンスレッドでやり通し、3つのすべてへの解決策を見つけました。</p>

<ul>
<li>Haskellのスレッドが外部呼び出しを行うと、他のOSのスレッドが残っているHaskellのスレッドの実行を引き継ぎます [ <a href="http://www.aosabook.org/en/bib2.html#concffi04">MPT04</a> ]。OSスレッドの小さなプールは、この目的のために保持され、新しいものは要求に応じて作成されます。</li>
<li><p>GHCのスケジューラは多くの軽量スレッドを幾つかの重たいOSスレッドに多重化します。これは透過的なM:Nスレッドモデルを実装します。典型的なNは、マシンのプロセッサコア数と同じになるように選択され、実際の並列処理が行われますが、各Haskellの軽量スレッドに対してフルのOSスレッドを持つオーバーヘッドはかかりません。</p>

<p>Haskellのコードが実行されるためにはOSスレッドが<em>Capability</em>を保持していなければいけません。Capabilityとはnurserly(新しいオブジェクトが生成されるメモリ)のように、Haskellのコードの実行に必要なリソースを保持するデータ構造のこと。ある時点でただ1つのOSスレッドのみが、与えられたCapabilityを保持することができます。（我々はこれを「Haskell Execution Context」とも呼んでいるが、コード上では現在Capabilityという用語を使っています。）</p></li>
<li><p><em>bound thread</em>を作成するためのAPIを提供しています。これは、1つの特定のOSスレッドに結び付けられたHaskellスレッドであり、このHaskellスレッドによるすべての外部呼び出しは、そのOSスレッドによって行われることが保証されています。</p></li>
</ul>

<p>したがって、大多数のケースでは、HaskellのスレッドはOSスレッドと全く同じように動作します。つまり、他のスレッドに影響を与えることなくOSコールをブロックし、マルチコアマシン上で並列実行することができます。しかし、それらは、時間と空間の両面で、より効率的なオーダーです。</p>

<p>しかし、この実装は、1つの問題を持っています。これには、ユーザーは時折、とりわけベンチマーク実行時に、衝突します。上で述べた通り、軽量スレッドは"safe points"でのみコンテキストスイッチを行うことで効率を引き出しています。コンパイラが安全であると示したコード上のポイント、そこでは内部状態（スタック、ヒープレジスタなど）が整理された状態にあり、ガベージコレクションが実行される可能性があります。GHCでは、メモリが割り当てられるたびに安全な点があります。ほとんどのHaskellプログラムでは、プログラムが安全な点にぶつかることなく数十以上の命令を実行することはありません。しかし、高度に最適化されたコードではメモリを割り当てることなく、多くの反復処理を行うことがありえます。これは、ベンチマーク（階乗やフィボナッチのような関数など）で頻繁に発生する傾向があります。それが実際のコードで起こることは非常に稀ではあるが、起きはします。安全なポイントがないと、スケジューラが実行されなくなり、有害な影響が生じる可能性があります。この問題を解決することは可能ですが、これらのループのパフォーマンスに影響を与えないことはありません。多くの場合、各サイクルを内部ループに保存することに注意しています。これは正に、私達が我慢しなければならない妥協かもしれない。 ￥</p>

<h2 id="56developingghc">5.6.　Developing GHC</h2>

<p>GHCは、20年生存する単一のプロジェクトであり、まだ革新と開発の変化の中にあります。ほとんどの場合、私たちのインフラとツールは従来のものでした。例えば、我々はバグトラッカー（Trac）とwiki(同じくTrac)、リビジョン管理にはGitを使っています。（このリビジョン管理の仕組みは、純粋な手動から始まり、CVS、それからDarcs、最終的に2010年にGitリポジトリに移行、と進展してきました）一般的ではないかもしれない幾つかの点があるので、それらを提示します。</p>

<h3 id="commentsandnotes">Comments and Notes</h3>

<p>大規模で長寿命なプロジェクトでの最も深刻な問題の一つは、技術文書を最新の状態に保つことです。私たちは銀の弾丸を持っていないが、私達をとりわけよく助けているローテクなメカニズムを提案します。それは <code>注釈</code> です。</p>

<p>コードを書くときには、慎重なプログラマーが精神的に「このデータ型は重要な不変性を持っている」のようなことを言う瞬間がしばしばあります。彼女は両方を満たすことはできない2つの選択に直面しています。彼女は不変性をコメントとして追加することができますが、データ型宣言が長すぎるため、コンストラクタが何であるか分かりにくいことがあります。代わりに、彼女は他の場所で不変性を文書化することもできますが、それがout of dateになるリスクがあります。20年間で、 <em>すべてが</em>古くなってしまいます！</p>

<p>このような動機から、私たちは、次のようなとても単純な規則を開発しました。</p>

<ul>
<li>意味のあるサイズのコメントは、コードで差し込まれるのではなく、標準形式で見出しが付いています。</li>
</ul>

<pre><code>  Note [Equality-constrained types]
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      The type   forall ab. (a ~ [b]) =&gt; blah
      is encoded like this:

         ForAllTy (a:*) $ ForAllTy (b:*) $
         FunTy (TyConApp (~) [a, [b]]) $
         blah
</code></pre>

<ul>
<li>コメントが関連している箇所で、我々は注釈を参照する短いコメントを追加します。</li>
</ul>

<pre><code> data Type
       = FunTy Type Type -- See Note [Equality-constrained types]

       | ...
</code></pre>

<p>コメントが何か興味深いことがあることを強調して、それを説明するコメントを正格に参照しています。それは些細に聞こえるが、「上記のコメントを参照してください」という以前の習慣よりも遥かに制度が向上しています。なぜなら、上記にあるたくさんのコメントの<em>どれ</em>を意図しているか明確では無いためや、数年後にはコメントが「上記」に残っていないためです（それは下記であったり全く違うところにあったりします）。</p>

<p><code>ノート</code>を参照するコードから<code>ノート</code>自体に進むことが可能なだけでなく、その逆も可能であり、それはしばしば有用です。さらに、コード内の複数のポイントから同じ<code>ノート</code>を参照することができます。</p>

<p>自動化されたサポートがないシンプルなASCII専用の技術は、私たちの生活を変えました。GHCは約800の<code>ノート</code>を持ち、その数は毎日増えています。</p>

<h3 id="howtokeeponrefactoring">How to Keep On Refactoring</h3>

<p>GHCのコードは、10年前と同じくらい速く騒動しています。同じ期間でシステムの複雑さが何倍も増加したことは間違いありません。 私たちは以前はGHCのコード量を計測していました。いまだ、システムは管理可能な状態です。私達はこれを3つの要因によるものだとしています。</p>

<ul>
<li>優れたソフトウェアエンジニアリングに勝るものはありません。コンポーネント間のAPIを可能な限り小さくすると、相互依存性がより少ないため、個々のコンポーネントの柔軟性が向上します。例えば、GHCの<code>Core {}</code>データ型が小さいと、Core-to-Coreパス間の結合を、それらがほぼ完全に独立しており、任意の順序で実行できる程度に、減少します。</li>
<li>強く型付けされた言語で開発することで、リファクタリングが容易になります。データ型を変更したり、関数の引数の数やデータ型を変更したりする必要があるときはいつでも、コンパイラがコードの他の場所を修正する必要があるかどうかをすぐに教えてくれます。単に、大きなクラスのエラーが静的に排除されていることを絶対に保証するだけで、特にリファクタリング時に、膨大な時間を節約できます。型システムが提供するのと同じレベルのカバレッジを手動で補う場合、いくつのテストケースになるのかは想像するのも恐ろしいです。</li>
<li><p>純粋に機能的な言語でプログラミングする場合、状態によるアクシデント的な依存関係を導入することは困難です。あなたが、突如、アルゴリズムの深い部分にアクセスする必要があると判断した場合に、命令型言語ではそれを必要な場所に明示的に渡していくのではなく、グローバルに参照できる状態を作るように誘惑されるかもしれません。このようにして、最終的には見えない依存関係が混じり、<em>脆いコード</em>となります。純粋な関数型プログラミングでは、すべての依存関係を明確にすることを強制します。それは新しい依存関係を追加することにいくらか負の圧力をかけます。そして、より少ない依存関係は良いモジュール性であることを意味します。確かに、新しい依存関係を追加する<em>必要</em>がある場合、純度性は依存関係を表現するためにより多くのコードを書かせますが、私たちの見解では、コードベースの長期的な健康の為に払う価値がコストです。</p>

<p>追加のメリットとして、純粋な関数型のコードは構造上スレッドセーフであり、並列化が容易な傾向があります。</p></li>
</ul>

<h3 id="crimedoesntpay">Crime Doesn't Pay</h3>

<p>成長してきたGHCの変化を振り返ると、共通の教訓が浮かび上がってきます。効率化と利便性の目的のどちらかは関係なく、純関数的ではないものは、道筋に悪影響を及ぼす傾向があります。私たちは数個の偉大な例を持っています。</p>

<ul>
<li><p>GHCは内部的に状態変更に依存するいくつかのデータ構造を使用します。一つは<code>FastString</code>タイプ。それは単一のグローバルハッシュテーブルを使用します。別のはグローバルな<code>NameCache</code>。これはすべての外部名が固有の番号が割り当てられていることを保証します。私達がGHCの並列化に挑戦したとき（つまり、GHCをマルチプロセッサ上で並列に複数のモジュールをコンパイルできるようにすること）、それらの状態変化に基づくデータ構造が<em>唯一</em>の粘着点でした。我々はこれらの場所での状態変化に頼っていなかったら、GHCの並列化は、ほとんど些細な事でしたでしょう。</p>

<p>実際に、プロトタイプの並列バージョンのGHCを構築しましたが、GHCは現在のところ並列コンパイルのサポートを含んでいません。しかしその主な理由は、これらの変更可能なデータ構造をスレッドセーフにするために必要な労力にまだ投資していないからです。</p></li>
<li><p>GHCの動作は、コマンドラインフラグによって大きく左右されます。これらのコマンドラインフラグはGHCの実行で与えられた定数で定義されているので、GHCの初期のバージョンでは、これらのフラグの値をトップレベルの定数として利用できました。たとえば、<code>Bool</code>型の最上位の値<code>opt_GlasgowExts</code>がありました。この値は、特定の言語拡張を有効にするかどうかを決定します。トップレベルの定数は、それらの値をアクセスする必要のあるすべてのコードに明示的に引数として渡す必要がないため、非常に便利です。</p>

<p>もちろん、これらのオプションは実行時に変更されるため、実際には<em>定数</em>ではありません。<code>opt_GlasgowExts</code>の定義では<code>unsafePerformIO</code>を呼び出す必要があります。それが副作用を隠すためです。それにもかかわらず、このトリックは、値が任意の実行内で一定であるため、通常、「十分に安全」とみなされます。 たとえば、コンパイラの最適化を無効にしません。</p>

<p>しかし、後にGHCは、単一モジュールコンパイラからマルチモジュールコンパイラに拡張されました。この時点で、異なるモジュールをコンパイルするときにフラグが異なる値を持つ可能性があるため、フラグのトップレベル定数を使用するトリックが壊れました。そこで、フラグを明示的に渡すために大量のコードをリファクタリングする必要がありました。</p>

<p>もしかしたら、あなたは命令型言語で自然なように、最初にフラグを<em>状態</em>として扱うことで問題を回避できたと主張するかもしれません。これはある程度真実ですが、純関数的なコードには他の多くの利点がありますが、不変なデータ構造によってフラグを表すことは、結果的にコードが既にスレッドセーフであり、修正なしで並列に実行されることを意味します。</p></li>
</ul>

<h3 id="developingtherts">Developing the RTS</h3>

<p>GHCのランタイムシステムは、多くの点で、コンパイラとはかなり対照的です。ランタイムシステムは、HaskellではなくCで書かれているという明確な違いもありますが、異なる設計思想を生み出すRTSへの特有の考慮事項もあります。</p>

<ol>
<li>すべてのHaskellプログラムはRTSでコードを実行するのに多くの時間を費やしています。20〜30％は典型的ですが、Haskellプログラムの特徴によってが大きく異なるため、この範囲より上下することも一般的です。RTSを最適化することによって節約される各サイクルは何度も何度も乗算されるので、これらのサイクルを節約するために多くの時間と労力を費やす価値があります。  </li>
<li>ランタイムシステムは静的にすべてのHaskellのプログラムにリンクされているので（動的リンクが使用されない限り）、それを小さく維持する動機があります。  </li>
<li><p>ランタイムシステムでのバグは、多くの場合、ユーザにとって不可解であり（"segmentation fault"等）、解決することは困難です。たとえば、ガベージコレクタのバグは、特定の言語機能の使用に結びつかない傾向があるが、いくつかの複雑な要因の組み合わせが実行時に現れる場合に発生します。さらに、この種のバグは非決定的（一部の実行でのみ発生する）かつ、とてもセンシティブ（プログラムの僅かな変更でバグが再現しなくなる）になる傾向があります。ランタイムシステムのマルチスレッド版のバグは、さらに大きな課題を提示します。したがって、これらのバグを予防することや、それらを簡単に確認できるインフラを構築することには、特別な期間を費やすことは価値があります。</p>

<p>RTSバグの症状は、多くの場合、他の2つの障害と区別がつきません。ハードウェアの障害、これはあなたが思っているより一般的かもしれません。または、FFI(Foreign Function Interface)のような安全でないHaskellの機能の仕様に誤りがある場合。実行時のクラッシュを診断する最初の仕事は、これら他の二つの原因を除外することです。</p></li>
<li><p>RTSは、いくつかの異なるアーキテクチャとオペレーティングシステム上で実行される低レベルのコードであり、それは定期的に新しいアーキテクチャに移植されます。移植性は重要です。</p></li>
</ol>

<p>すべてのサイクル、すべてのバイトが重要ですが、正当性はなおさらです。また、ランタイムシステムによって実行されるタスクは、本質的に複雑であるため、正当性で始まるのは難しいです。これらを両立することは、いくつかの興味深い守備技術を私たちに導き出させます。これについて次のセクションで説明します。</p>

<h4 id="copingwithcomplexity">Coping With Complexity</h4>

<p>RTSは、複雑で不利なプログラミング環境です。コンパイラとは対照的に、RTSは殆ど型安全性がありません。実際、他のほとんどのCプログラムよりも型の安全性が低くなっています。それは、Haskellレベルの型で、Cレベルでは存在しない型を持つデータ構造を管理するためです。例えば、RTSは、cons cellの末尾が指し示すオブジェクトが<code>[]</code>を指しているのか、別のconsを指しているのかを知りません。この情報は単にCレベルには存在しません。また、Haskellのコードをコンパイルするプロセスは、型を消去し、私たちはcons cellの末尾がリストであるとRTSに告げたとしても、それはまだcons cellの先頭へのポインタについての情報を持っていないだろう。故に、RTSコードはCのポインタ型のキャストの多くを行う必要があり、それはCコンパイラから型安全性についてほんの少しの助けしか得られません。</p>

<p>この戦いでの私たちの最初の武器は、<em>RTSにコードを入れないようにすること</em>です。可能な限り、我々はRTSへは最小限の機能を入れ、Haskellのライブラリに残りを書きます。これはめったに悪くはない。 HaskellのコードはCよりはるかに堅牢で簡潔であり、通常はパフォーマンスも完全に受け入れられます。多くの場合、それが合理的に明らかであるが、どこに行を追加すべきか、正確に科学的ではありません。例えば、Haskellでガベージコレクタを実装することは理論的には可能かもしれませんが、実際にはそれは極めて難しい。なぜなら、Haskellはプログラマがメモリ割り当てを正確に制御できないため、この種の低レベルなタスクをCに落とすことは、実践的な判断です。</p>

<p>Haskellでは（簡単に）実装することはできない多くの機能があり、RTSにコードを書くことは楽しいことではありません。次のセクションでは、RTSにおいて複雑さと正確性を管理する1つの側面に焦点を当てます。不変条件を維持する。</p>

<h3 id="invariantsandcheckingthem">Invariants, and Checking Them</h3>

<p>RTSは不変条件で満たされています。それらの多くはささいで簡単にチェックできます。たとえば、キューの先頭へのポインタが<code>NULL</code>の場合、末尾へのポインタも<code>NULL</code>にする必要があります。 RTSのコードには、このようなチェックをするためのアサーションが散りばめられています。アサーションは、バグが現れる前に発見するためのツールです。 実際、新しい不変条件が追加される際、不変条件を実装するコードを書く前にアサーションを追加することがよくあります。</p>

<p>ランタイムの不変条件の中には、満たすことや確認することがはるかに難しいものがあります。この手の不変条件のうち、他よりも多くのRTSに広がっているのは、次のとおりです。<em>ヒープはダングリングポインタを持っていない</em></p>

<p>ダングリングポインタは容易に発生し、コンパイラとRTS自体の両方がこの不変条件を破壊することができる多くの場所があります。コードジェネレータは、無効なヒープオブジェクトを作成するコードを生成する可能性があります。 ガベージコレクタは、ヒープをスキャンするときにオブジェクトのポインタを更新するのを忘れるかもしれません。この種のバグを追跡することは、非常に時間がかかることがあります（しかしながら、著者の好きなアクティビティの一つです！）。それは、プログラムが実際にクラッシュするまでに、ダングリングポインタが発生した場所から、実行が進んでしまっているためです。利用可能なデバッグツールがありますが、プログラムを逆順で実行するのは得意では無い傾向があります。（ただし、最近のGDBとMicrosoft Visual Studioデバッガでは、いくつかの逆実行をサポートしています）。</p>

<p>一般的な原理は、 <em>プログラムがクラッシュしようとしている場合、それは、可能な限り、すぐに、うるさく、頻繁に、クラッシュすべきである</em>。 （この引用は、GHCコーディングスタイルのガイドラインに由来し、もともとRTSの初期バージョンで作業していたAlastair Reidによって書かれました）。</p>

<p>問題は、「ダングリングポインタでない不変式」を定数時間内のアサーションでチェックできないということです。それをチェックするアサーションは、ヒープの完全な走査を行う必要があります！明らかに、すべてのヒープの割当のたびに、またはGCがオブジェクトをスキャンするたびに、このアサーションを実行することはできません（実際には、メモリが解放されるまで、ダングリングポインタはGCの最後まで現れないため、これも十分ではありません）。</p>

<p>そこで、RTSデバッグは、我々が<em>sanity checking</em>と呼ぶオプションのモードがあります。sanity checkingは、高価なアサーションのすべての種類を有効にし、プログラムをよりゆっくりと何度も実行することができます。具体的には、sanity checkingは、すべてのGCの<em>前後</em>に、(主に)ダングリングポインタをチェックするために、ヒープの完全スキャンを実行します。ランタイムクラッシュを調査するときに最初にスべきことは、sanity checkingをオンにしてプログラムを実行することです。 プログラムが実際にクラッシュする前に不変式の違反を捕捉することがあります。</p>

<h2 id="57conclusion">5.7. Conclusion</h2>

<p>GHCは20年の間で著者の生活のかなりの部分を消費してきました。GHCはHaskellの唯一の実装ではありませんが、何十万人もの人が実際の作業を行うために常用している唯一のものです。ハスケルが以外な場所で使われた時に、私たちはいつも驚いています。 最近の例の1つは、Haskellが<a href="http://www.haskell.org/pipermail/haskell-cafe/2010-April/075647.html">ゴミトラックのシステムを制御</a>するために使用されていることです。</p>

<p>多くの人にとってHaskellとGHCは同義です。それは全く意図していなかったことであり、実際のいろいろな場合において、標準に対してただひとつの実装を持つことは逆効果です。しかし、実際のところ、プログラミング言語の優れた実装を維持することは大きな仕事です。GHCの、「標準をサポートし、各言語拡張は明確に区切る取り組み」によって、より多くの実装が出現し、パッケージシステムやその他のインフラと統合できるようになることを願っています。競争はすべての人にとって良いことです！</p>

<p>私達の研究の一環としてGHCを開発し、オープンソースとして配布する機会を与えてくださったMicrosoftにとりわけの感謝を捧げます。</p>

<hr>

<p>This work is made available under the <a href="http://creativecommons.org/licenses/by/3.0/legalcode">Creative Commons Attribution 3.0 Unported</a> license. Please see the <a href="http://www.aosabook.org/en/intro1.html#license">full description of the license</a> for details.</p>

<p><a href="http://www.aosabook.org/en/ghc.html#">Back to top</a> <br>
<a href="http://www.aosabook.org/en/index.html">Back to <em>The Architecture of Open Source Applications</em>.</a></p>]]></content:encoded></item><item><title><![CDATA[GHCでCall Stackを表示する]]></title><description><![CDATA[<p>テストのassertationやエラーログなどで使う。</p>

<p>GHC.Stackを使うとstackを取得できる。</p>

<pre><code>{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ImplicitParams #-}

import Data.Text (Text)  
import GHC.Stack

main = do  
    putStrLn "before error"
    printStack  - line 9
    putStrLn "after error"


printStack = do  
    putStrLn . show . head . reverse . getCallStack $ ?loc -- line 14
</code></pre>

<p>Output  </p>

<pre><code>before error  
("?loc",SrcLoc {srcLocPackage = "main", srcLocModule = "Main"</code></pre>]]></description><link>http://blog.nakaji.me/callstackwobiao-shi-suru/</link><guid isPermaLink="false">1e29e698-f7dc-419e-80a8-fe262599d160</guid><category><![CDATA[Haskell]]></category><category><![CDATA[Test]]></category><category><![CDATA[Debug]]></category><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Mon, 11 Jul 2016 06:09:16 GMT</pubDate><content:encoded><![CDATA[<p>テストのassertationやエラーログなどで使う。</p>

<p>GHC.Stackを使うとstackを取得できる。</p>

<pre><code>{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ImplicitParams #-}

import Data.Text (Text)  
import GHC.Stack

main = do  
    putStrLn "before error"
    printStack  - line 9
    putStrLn "after error"


printStack = do  
    putStrLn . show . head . reverse . getCallStack $ ?loc -- line 14
</code></pre>

<p>Output  </p>

<pre><code>before error  
("?loc",SrcLoc {srcLocPackage = "main", srcLocModule = "Main", srcLocFile = "app/Main.hs", srcLocStartLine = 14, srcLocStartCol = 55, srcLocEndLine = 14, srcLocEndCol\
 = 59})
after error  
</code></pre>

<p>ここで、printStackに制約を付け足すと、ここでのstackは無視されるようになる。</p>

<pre><code>printStack :: (?loc :: CallStack) =&gt; IO ()  
</code></pre>

<p>Output  </p>

<pre><code>before error  
("printStack",SrcLoc {srcLocPackage = "main", srcLocModule = "Main", srcLocFile = "app/Main.hs", srcLocStartLine = 9, srcLocStartCol = 5, srcLocEndLine = 9, srcLocEnd\
Col = 15})  
after error  
</code></pre>]]></content:encoded></item><item><title><![CDATA[突然android端末が認識されなくなったら]]></title><description><![CDATA[<p>まずは何も考えず</p>

<pre><code>adb kill-server
adb start-server
</code></pre>]]></description><link>http://blog.nakaji.me/tu-ran-androidduan-mo-garen-shi-sarenakunatutara/</link><guid isPermaLink="false">fc63f981-4b17-4d10-aaf6-18655da4c304</guid><dc:creator><![CDATA[Daishi Nakajima]]></dc:creator><pubDate>Wed, 11 May 2016 08:29:56 GMT</pubDate><content:encoded><![CDATA[<p>まずは何も考えず</p>

<pre><code>adb kill-server
adb start-server
</code></pre>]]></content:encoded></item></channel></rss>