Mercurial > hg > Papers > 2014 > toma-master
changeset 49:0a8d66c9ccd1
describe the impl
author | Daichi TOMA <toma@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 08 Feb 2014 10:09:04 +0900 |
parents | 88b11a3afb93 |
children | 37d54a95bf84 |
files | paper/appendix1.tex paper/chapter1.tex paper/chapter2.tex paper/chapter3.tex paper/chapter4.tex paper/master_paper.pdf slides/images/jungle_type.graffle |
diffstat | 7 files changed, 564 insertions(+), 606 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/appendix1.tex Fri Feb 07 01:02:26 2014 +0900 +++ b/paper/appendix1.tex Sat Feb 08 10:09:04 2014 +0900 @@ -13,7 +13,7 @@ 接続には, HTTP Keep-Alivesを利用する. 新しい TCP 接続を確立するのはとても遅く, OS カーネルによって行われる. -毎秒多くの新しい接続を作成するようなベンチマークを行うと, OSカーネルのテストとなってしまう. +毎秒多くの新しい接続を作成するベンチマークを行うと, OSカーネルのテストとなってしまう. アプリケーションやOSカーネルが完全にハードウェアを使用できるようにするためにいくつか調整を行う必要がある. 最初の問題は, ファイル記述子の欠如である. @@ -83,7 +83,7 @@ また, テストするサーバより遅いベンチマーククライアントを用いると正しい結果は得られない. シングルスレッドで稼働したり, Ruby や Python といった低速なベンチマークツールでテストを行うと, -すべてのテストする対象が同じようなパフォーマンスを持っているように見えてしまう. +すべてのテストする対象が同じパフォーマンスを持っているように見えてしまう. \subsubsection{weighttp} ウェブアプリケーションの性能測定には, weighttpを用いる.
--- a/paper/chapter1.tex Fri Feb 07 01:02:26 2014 +0900 +++ b/paper/chapter1.tex Sat Feb 08 10:09:04 2014 +0900 @@ -155,7 +155,7 @@ 返り値となる型は, elemsの[a]となる. このaは, elemsが受け取るMapの2つ目の型と一致するため, childrenの返り値であるMap Int Node より, [Node]ということが分かる. Haskell では, プログラマが型の宣言を行わずとも, 型を推論し型安全を保つ. -しかしながら, 明示的な型宣言は可読性の向上や問題の発見に役に立つため, トップレベルの関数には型を明記することが一般的である. +しかし, 明示的な型宣言は可読性の向上や問題の発見に役に立つため, トップレベルの関数には型を明記することが一般的である. \section{モナド} Haskell では, さまざまな目的にモナドを使う. @@ -394,7 +394,7 @@ rpar で作成した Eval モナドを runEval に渡したあと、値が必要となるprintなどを行えば, 並列に実行可能な部分が並列に実行される. また, rpar を使用する際, 別の計算の値に依存する計算がある場合, その2つの計算は並列実行できない. -例えば, ソースコード\ref{src:rpar}のような場合は並列実行ができない. +例えば, ソースコード\ref{src:rpar}の場合は並列実行ができない. \begin{lstlisting}[label=src:rpar, caption=前の計算に依存した計算] test2 :: Eval (Integer, Integer)
--- a/paper/chapter2.tex Fri Feb 07 01:02:26 2014 +0900 +++ b/paper/chapter2.tex Sat Feb 08 10:09:04 2014 +0900 @@ -86,4 +86,4 @@ ルートノードの情報の更新の場合は, 他から変更があれば再度やり直すということが自動的に行われる. 以前の実装では, ルートノードだけではなく非破壊的木構造全体をSTMで管理していた\cite{toma:2013}. -しかしながら, 非破壊的木構造全体をSTMで管理すると並列実行時に性能が出ないため, ルートノードのみの管理に変更を行った. +しかし, 非破壊的木構造全体をSTMで管理すると並列実行時に性能が出ないため, ルートノードのみの管理に変更を行った.
--- a/paper/chapter3.tex Fri Feb 07 01:02:26 2014 +0900 +++ b/paper/chapter3.tex Sat Feb 08 10:09:04 2014 +0900 @@ -15,11 +15,14 @@ \end{enumerate} \subsubsection{Jungle が持つデータ型} -Jungle が持つのデータ型を表\ref{tab:components}に表す. +非破壊的木構造データベース Jungle が持つのデータ型を表\ref{tab:components}に表す. +また, データ型内部のデータ構造を\ref{tab:components2}に表す. + 木構造の集まりを表現する Jungle, 単体の木構造を表現する Tree がある. Node は子と属性を任意の数持てる. -データ型として定義することで, データ内部の型の整合性が保たれ, また型検査でエラーがないか検出することができる. -Jungle のデータ型について, ひとつずつ説明する. +データ型として定義することで, 内部の型の整合性が保たれる. +例えば, Node の1つ目の型は (Map Int Node) となり他の型は許されない. +非破壊的木構造データベース Jungle のデータ型について, ひとつずつ説明する. \begin{table}[!htbp] \label{tab:components} @@ -35,7 +38,7 @@ \end{table} \begin{table}[!htbp] -\label{tab:components} +\label{tab:components2} \begin{center} \begin{tabular}{|c||c|} \hline 型名 & データ構造 \\ \hline @@ -49,9 +52,9 @@ \subsection{Jungle} Jungle は木構造の集まりを表現する. -木には名前がついており, Tree の情報と一緒に保持している. +木には名前がついており, Tree の情報と一緒に保持している(ソースコード\ref{src:jungle}). -\begin{lstlisting}[caption=Jungleのデータ型の定義] +\begin{lstlisting}[label=src:jungle, caption=Jungleのデータ型の定義] data Jungle = Jungle { getJungleMap :: (TVar (Map String Tree)) } \end{lstlisting} @@ -59,12 +62,12 @@ getJungleMap :: というのは, Haskell のレコード構文である. レコード構文は, データ構造へのアクセサを提供する. -getJungleMap は関数で, 以下のような型を持つ. +getJungleMap は関数で, ソースコード\ref{src:getjunglemap}の型を持つ. これは, Jungleを受け取って, TVar (Map String Tree)を返す関数である. レコード構文はデータ型を受け取って, :: の右側の型の値を取り出せる関数を作成すると思えば良い. -\begin{lstlisting}[caption=getJungleMap] +\begin{lstlisting}[label=src:getjunglemap, caption=getJungleMap] getJungleMap :: Jungle -> TVar (Map String Tree) \end{lstlisting} @@ -106,11 +109,12 @@ Jungle のデータ構造の Map の前に付いている TVar というのは, Transactional variablesの略で, STM で管理する変数に対して利用する. \subsubsection{Jungle と木の作成} -Jungle は, 複数の非破壊的木構造を持つため、Map で木を管理している(図\ref{fig:jungle}). +Jungle は, 複数の非破壊的木構造を持つため, Map で木を管理している(図\ref{fig:jungle}). +Tree には名前がついており, 複数のバージョンの Tree のノードのどれが最新かという情報を持っている. \begin{figure}[!htbp] \begin{center} -\includegraphics[scale=0.7]{./images/jungle.pdf} +\includegraphics[scale=0.7]{./images/jungle_type.pdf} \end{center} \caption{複数の木を扱えるJungle} \label{fig:jungle} @@ -119,17 +123,23 @@ 木構造の識別, つまり Map の キー にはString を利用する. String は Haskell の文字列の型で, Char のリスト [Char] の別名である. -Jungle を作成するには, createJungle を用いる. +Jungle を作成するには, createJungle を用いる(ソースコード\ref{src:createJungle}). empty は空のMapを作成する関数である. -\begin{lstlisting}[caption=createJungle] +\begin{lstlisting}[label=src:createJungle, caption=createJungle] createJungle :: IO Jungle createJungle = atomically $ do map <- newTVar empty return (Jungle map) \end{lstlisting} -\begin{lstlisting}[caption=STMの関数] + +createJungleは, 新たにSTMの変数を作成する newTVar を実行する. +newTVar などの STM の操作は STM モナド内で行う. +最後にatomicallyを行うことで, do 構文内がトランザクションとして実行される. +STMの関数が持つ型をソースコード\ref{src:stm}に示す. + +\begin{lstlisting}[label=src:stm, caption=STMの関数] newTVar :: a -> STM (TVar a) readTVar :: TVar a -> STM a writeTVar :: TVar a -> a -> STM () @@ -137,15 +147,11 @@ atomically :: STM a -> IO a \end{lstlisting} -createJungleは, 新たにSTMの変数を作成する newTVar を実行する. -newTVar などの STM の操作は STM モナド内で行う. -最後にatomicallyを行うことで, do 構文内がトランザクションとして実行される. - atomically の隣にある \$ は関数適用演算子である. \$ 関数は最も低い優先順位を持っており, 右結合である. -括弧を減らすのに使う. \$ を使わない場合は以下の様に記述することになる. +括弧を減らすのに使う. \$ を使わない場合はソースコード\ref{src:dollar}の様に記述することになる. -\begin{lstlisting}[caption=STMの関数] +\begin{lstlisting}[label=src:dollar, caption=関数適用演算子を使わない場合] createJungle :: IO Jungle createJungle = atomically (do map <- newTVar empty @@ -156,22 +162,22 @@ \subsection{Tree} Jungleが保持する木の情報は, 内部的には Tree というデータ型で保持している. -Tree は木の名前と, ルートノードの情報を持っている. +Tree は木の名前と, ルートノードの情報を持っている(ソースコード\ref{src:tree}). 実際にユーザがJungleを利用する際は, Jungle と木の名前を使ってルートノードを取ってくるため, Tree という構造は見えない. ルートノードの情報はスレッド間で状態を共有する必要がある. スレッドセーフに取り扱う必要があるため, この情報も Haskell の ソフトウェア・トランザクショナル・メモリ (STM) を用いて管理している. -\begin{lstlisting}[caption=Treeのデータ型の定義] +\begin{lstlisting}[label=src:tree,caption=Treeのデータ型の定義] data Tree = Tree { rootNode :: (TVar Node) , treeName :: String } \end{lstlisting} -新たな非破壊的木構造を作るには, createTree を用いる. +新たな非破壊的木構造を作るには, createTree を用いる(ソースコード\ref{src:createTree}). createTree は, createJungleで作成した Jungle と木の名前を String で受け取る. -\begin{lstlisting}[caption=createTree] +\begin{lstlisting}[label=src:createTree, caption=createTree] createTree :: Jungle -> String -> IO () createTree (Jungle tmap) tree_name = atomically $ do map <- readTVar tmap @@ -188,13 +194,14 @@ \end{lstlisting} createJungleも STM を操作するため IOを返す. -Jungle の持つ, tmapをreadTVarで取得し, 複数の木構造を管理するためのMapを取得する. -STM の変数をもった Tree を作成し, Map に insert する. +Jungle の持つ, 複数の木構造と名前を関連付けた Map をreadTVarで取得する. +ルートノードの管理のための STM の変数をもった Tree を作成し, Jungle の Map に insert する. +そして最後に writeTVar を用いて STM を更新する. writeTVar は更新する先の変数と, 更新内容の2つを受け取る STM の関数である. -実際にcreateJungleとcreateTreeを使う時は以下のように記述する. +実際にcreateJungleとcreateTreeを利用する時はソースコード\ref{src:createdatabase}のように記述する. -\begin{lstlisting}[caption=データベースと木の作成] +\begin{lstlisting}[label=src:createdatabase,caption=データベースと木の作成] main = do jungle <- createJungle createTree jungle "name of new tree here" @@ -214,12 +221,20 @@ \end{figure} ルートノードに関する関数を説明する. - getRootNode は, 最新のルートノードを取得できる. データベースと木の名前を渡すことで利用できる. 例えば, 図\ref{fig:getrootnode}の状態の時は, B というルートノードが取得できる. -\begin{lstlisting}[caption=最新のルートノードの取得] + +getRootNode 関数の定義を示す(\ref{src:getrootnode}). +まず, readTVarでJungleが持つmapを参照する. +Haskell の where キーワードは, 計算の中間結果に名前をつけるために用いられる. +今回は, root\_node という map を受け取る関数を定義している. +root\_node map では, Jungle が持つ Map をみて取得しようとしている名前の木構造があるかどうか調べている. +木構造があった場合, rootNodeというTreeに定義されているレコード構文のアクセサ関数を使って, (TVar Node)を取得する. +最後に, (TVar Node)に対して, readTVarを行うことで最新のルートノードが取得できる. + +\begin{lstlisting}[label=src:getrootnode, caption=最新のルートノードの取得] getRootNode :: Jungle -> String -> IO Node getRootNode (Jungle tmap) tree_name = atomically $ do map <- readTVar tmap @@ -229,19 +244,15 @@ Just x -> rootNode x \end{lstlisting} -まず, readTVarでJungleが持つmapを参照する. -Haskell の where キーワードは, 計算の中間結果に名前をつけるために用いられる. -今回は, root\_node という map を受け取る関数を定義している. -root\_node map では, Jungle が持つ Map をみて取得しようとしている名前の木構造があるかどうか調べている. -木構造があった場合, rootNodeというTreeに定義されているレコード構文のアクセサ関数を使って, (TVar Node)を取得する. -最後に, (TVar Node)に対して, readTVarを行うことで最新のルートノードが取得できる. - 木構造を編集する関数は全て Node を受け取って Node を返す. その返ってきた Node をルートノードとして登録することで, 木構造の最新のルートノードが更新される. updateRootNode は, データベースと木の名前, 変更して返ってきた木構造の 3 つを渡す. updateRootNodeをした後は, getRootNodeで取得できるルートノードが更新された状態になっている. -\begin{lstlisting}[caption=ルートノードの更新] +updateRootNode 関数の定義を示す(\ref{src:updaterootnode}). +getRootNodeと同じように, Treeの(TVar Node)を取得し, 最後にwriteTVarを用いて更新している. + +\begin{lstlisting}[label=src:updaterootnode, caption=ルートノードの更新] updateRootNode :: Jungle -> String -> Node -> IO () updateRootNode (Jungle tmap) tree_name node = atomically $ do @@ -254,9 +265,12 @@ updateRootNodeWithは, ノードを更新する関数とデータベース, 木の名前を渡して利用する. ノードを更新する関数とは, ノードを受け取ってノードを返す関数である. (Node $->$ Node) がそれにあたる. -このupdateRootNodeWithを利用することで, getRootNodeをした後に編集しupdateRootNodeを行う一連の操作がatomicallyに行われることが保証される. +このupdateRootNodeWithを利用することで, getRootNodeをした後に編集しupdateRootNodeを行う一連の操作が分断されずに行われることが保証される. +updateRootNode 関数の定義を示す(\ref{src:updaterootnodewith}). +updateRootNodeWithでは, 一連の操作を分断せずに行うためにreadTVarからwriteTVarまで同じ STM モナド内で行っている. +atomicallyに関数にdo構文で繋げたSTMモナドを渡すことで, このブロックがトランザクションとして実行される. -\begin{lstlisting}[caption=ルートノードの更新] +\begin{lstlisting}[label=src:updaterootnodewith, caption=ルートノードの更新] updateRootNodeWith :: (Node -> Node) -> Jungle -> String -> IO () updateRootNodeWith f (Jungle tmap) tree_name = atomically $ do @@ -272,7 +286,7 @@ createJungle, createTree, getRootNode, updateRootNode, updateRootNodeWith で全てである. 並列データベース Jungle では, なるべく状態を共有しないようにすることで並列実行時の性能の向上を実現する. -ソフトウェアトランザクショナルメモリは書き込み時に他から変更があった場合にやり直しという操作はあるものの, 読み込みに関してはロックなしで高速に読み込める. +ソフトウェアトランザクショナルメモリは書き込み時に他から変更があった場合にやり直しという操作はあるものの, 読み込みに関してはノンブロッキングで高速に読み込める. \subsection{Node} Node は木構造を表現するデータ構造である. @@ -301,7 +315,7 @@ 非破壊的木構造を利用しているため, getRootNode などで取得してきた Node は他のスレッドと干渉することなく自由に参照, 編集できる. これらの編集のための関数は, 編集後updateRootNodeするか, ひとつの関数にまとめてupdateRootNodeWithをすることで木構造に反映させることができる. -編集対象のノードを指定するには, NodePath を利用する. +編集対象のノードを指定するには, NodePath を利用する(図\ref{fig:nodepath}). NodePath は, ルートノードからスタートし, ノードの子どもの場所を次々に指定したものである. Haskell の基本データ構造であるリストを利用している. @@ -314,32 +328,37 @@ \end{figure} 木の編集を行う関数を紹介する. +木の編集を行う関数の型の定義をソースコード\ref{src:editfunc_type}に示す. -\begin{lstlisting}[caption=木の編集を行う関数] +\begin{lstlisting}[label=src:editfunc_type, caption=木の編集を行う関数] addNewChildAt :: Node -> Path -> Node deleteChildAt :: Node -> Path -> Position -> Node putAttribute :: Node -> Path -> String -> ByteString -> Node deleteAttribute :: Node -> Path -> String -> Node \end{lstlisting} -addNewChildAt で, ノードに新しい子を追加できる. -Node と NodePath を渡す必要がある. -子には Position という場所の情報があるが, インクリメントしながら自動的に指定される. +\paragraph*{addNewChildAt} +ノードに新しい子を追加できる. +更新対象となる木構造の Node と, どこに追加するかの情報である NodePath を渡す必要がある. +子の場所は, インクリメントしながら自動的に指定される. -deleteChildAt で, ノードの子を削除できる. -Node と NodePath, 削除したい子のPositionを指定する. +\paragraph*{deleteChildAt} +ノードの子を削除できる. +更新対象となる木構造の Node と, どこのノードの子を削除するかという情報である NodePath, 削除したい子の場所を指定する Position を渡す必要がある. -putAttribute で, ノードに属性を追加できる. -Node と NodePath, キー, 値を渡す. -キーは String, 値は, ByteString である. +\paragraph*{putAttribute} +ノードに属性を追加できる. +更新対象となる木構造の Node と, どこに属性を追加するかの情報である NodePath を渡す必要がある. +属性はキーと値があり, キーは String, 値は ByteString である. -deleteAttribute で, ノードの属性を削除できる. -Node と NodePath, キーを渡す. +\paragraph*{deleteAttribute} +ノードの属性を削除できる. +更新対象となる木構造の Node と, どこの属性を削除するかの情報である NodePath, 削除したい属性のキーである String を渡す必要がある. これらの関数は, ほぼ同一の関数で定義できる. -addNewChildAtを用いて説明する. +addNewChildAtを用いて説明する(ソースコード\ref{src:addNewChildAt}). -\begin{lstlisting}[caption=木の編集を行う関数] +\begin{lstlisting}[label=src:addNewChildAt, caption=木の編集を行う関数] addNewChildAt :: Node -> Path -> Node addNewChildAt parent [] = addChildAt parent emptyNode addNewChildAt parent (x:xs) = addChild parent x $ addNewChildAt x_node xs @@ -366,8 +385,8 @@ 非破壊的木構造の編集は再帰で定義できる. 左結合となる\$を使い, 対象のノードに到達するまで, addChildを繰り返す. -addChildは, 引数として子となるノードが必要である. -そのため, 下の階層から徐々に上に作られていく. +addChildは, 指定したノードのPositionに子を追加する. 引数として子となるノードが必要である. +addChildを繰り返すことで, 下の階層から徐々に上に作られていく. addNewChildAt, deleteChildAt, putAttribute, deleteAttributeといった, 非破壊的木構造の編集は, 対象のノードに対する操作以外は全て同じである. @@ -375,12 +394,18 @@ 新しい子を追加するのが addNewChildAt, 指定されたポジションの子を削除するのが deleteChildAt, 指定されたキーと値を追加するのが putAttribute, 指定されたキーの値を削除するのが deleteAttributeである. +\subsubsection{木の参照} +木の参照にも参照対象となる木構造の Node を用いる. +参照関数の定義をソースコード\ref{src:reffunc}に示す. -\subsubsection{木の参照} -木の参照にも Node を用いる. -様々な参照の関数があるため, ひとつずつ紹介していく. - -\begin{lstlisting}[caption=属性の取得] +\begin{lstlisting}[label=src:reffunc, caption=参照関数] +getNode :: Node -> Path -> Node +getNode node [] = node +getNode node (x:xs) = getNode child xs + where + map = children node + child = case M.lookup x map of + Just x -> x getAttributes :: Node -> Path -> String -> Maybe ByteString getAttributes node path key = lookup key map where @@ -419,34 +444,31 @@ pos = size map \end{lstlisting} -elems, assocs, sizeなどはData.Mapの関数である. +参照関数の基本的な流れは、getNode関数を使って参照したいPathのノードを取ってくることである. +そのノードにはwhereキーワードを利用して、targetという名前をつけている. +targetに対して、子のMapや属性のMapを取得した後、lookup関数などを適用する. +elems, assocs, sizeなどはData.Mapの参照関数で、Jungle ではその関数をそのまま利用している. -getAttributes は, 対象の Path に存在する属性を Key を用いて参照できる. +参照関数の基本的な機能をまとめて説明する. -getChildren は, 対象の Node が持つ全ての子を Node のリストとして返す. +\paragraph*{getAttributes} +対象の Path に存在する属性を Key を用いて参照できる. + +\paragraph*{getChildren} +対象の Node が持つ全ての子を Node のリストとして返す. あるNodeに存在する全ての子に対して, 参照を行いたい場合に利用する. -assocsChildren は, 対象の Node が持つ全ての子を Position とのタプルにし, そのタプルのリストを返す. +\paragraph*{assocsChildren} +対象の Node が持つ全ての子を Position とのタプルにし, そのタプルのリストを返す. あるNodeに存在する全ての子に対して, 子のPositionを取得しながら参照を行いたい場合に利用する. -assocsAttribute は, 対象の Node が持つ全ての属性を, キーと値のペアとし, そのペアのリストを返す. +\paragraph*{assocsAttribute} +対象の Node が持つ全ての属性を, キーと値のペアとし, そのペアのリストを返す. あるNodeに存在する全ての属性に対して, 参照を行いたい場合に利用する. -numOfChild では, 対象の Node が持つ子どもの数を取得できる. - -currentChild では, 対象の Node が持つ最新の子を取得できる. - +\paragraph*{numOfChild} +対象の Node が持つ子どもの数を取得できる. -\subsubsection{並列実行} -木構造データベース Jungle は, 並列に実行することができる. -アプリケーション側で, データベースを参照や変更する際に各スレッドから呼び出しても問題ない. -利用方法も, シングルスレッドで実行する場合と同じである. +\paragraph*{currentChild} +対象の Node が持つ最新の子を取得できる. -\section{Haskell の生産性} -Java を用いた Jungle の実装と比較して, コード行数が約 3000 行から約 300 行へと短くなった. - -Haskell では, 独自のデータ型を作成することができる. -再帰的なデータ構造の定義も容易である. -また, Haskellは参照透過性を持つため, コードの再利用が行い易く, 関数同士の結合も簡単である. - -同じような機能を実装する場合でも, Java と比較してコード行数が短くなり生産性が向上する.
--- a/paper/chapter4.tex Fri Feb 07 01:02:26 2014 +0900 +++ b/paper/chapter4.tex Sat Feb 08 10:09:04 2014 +0900 @@ -218,7 +218,7 @@ Warp のボトルネックがどれぐらいあるのか調査するために, アクセスした際に "hello, world" という文字列を返すだけのプログラムを作成し測定する. 結果を表\ref{tab:warp}に示す. 1 スレッドで実行した場合は, Jungle と組み合わせた掲示板より速い. -しかしながら, スレッド数が増えていくと掲示板の読み込みとあまり結果が変わらなくなってしまう. +しかし, スレッド数が増えていくと掲示板の読み込みとあまり結果が変わらなくなってしまう. Warp は現状あまり並列化効果がでていない. \begin{table}[!htbp] @@ -313,7 +313,7 @@ thunkとは, 未評価の式を追跡するのに使われるものである. 遅延評価は, グラフ簡約があるため先行評価より簡約ステップ数が増えることはない. また, 不要な計算が省かれるので簡約ステップ数が少なくなることもある. -しかしながら, 計算の所用領域が増えてしまうのが難点で, +しかし, 計算の所用領域が増えてしまうのが難点で, ハードウェアが効率的に利用できるメモリの範囲内に収まらなければ即時評価より実行時間が遅くなってしまうことがあるので注意が必要である. 本実験では, 潤沢にメモリを割り当てているためそういった問題は起きない. @@ -339,3 +339,12 @@ 結果が明らかに遅くなっている. 12 スレッドで実行した際, Java との書き込みの性能差は, 1.30 倍である. シングルスレッドで実行した場合と比較した場合, 12 スレッドで 2.40 倍の性能向上が見られる. + +\section{Haskell の生産性} +Java を用いた Jungle の実装と比較して, コード行数が約 3000 行から約 300 行へと短くなった. + +Haskell では, 独自のデータ型を作成することができる. +再帰的なデータ構造の定義も容易である. +また, Haskellは参照透過性を持つため, コードの再利用が行い易く, 関数同士の結合も簡単である. + +同じ機能を実装する場合でも, Java と比較してコード行数が短くなり生産性が向上する.
--- a/slides/images/jungle_type.graffle Fri Feb 07 01:02:26 2014 +0900 +++ b/slides/images/jungle_type.graffle Sat Feb 08 10:09:04 2014 +0900 @@ -53,6 +53,414 @@ <array> <dict> <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3234</integer> + </dict> + <key>ID</key> + <integer>3235</integer> + <key>Points</key> + <array> + <string>{403.50001775468951, 253.50001501742369}</string> + <string>{403.50001775468951, 278.49999681521825}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3222</integer> + </dict> + </dict> + <dict> + <key>Class</key> + <string>Group</string> + <key>Graphics</key> + <array> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3229</integer> + </dict> + <key>ID</key> + <integer>3224</integer> + <key>Points</key> + <array> + <string>{413.98077454043232, 308.73898904300546}</string> + <string>{415.86117803332991, 313.58495392846555}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>HeadScale</key> + <real>0.5</real> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3232</integer> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3232</integer> + </dict> + <key>ID</key> + <integer>3225</integer> + <key>Points</key> + <array> + <string>{406.21216953698865, 291.41209310886637}</string> + <string>{408.53694561526197, 296.6213493439032}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>HeadScale</key> + <real>0.5</real> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3234</integer> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3230</integer> + </dict> + <key>ID</key> + <integer>3226</integer> + <key>Points</key> + <array> + <string>{398.40791616334388, 308.63247304283414}</string> + <string>{400.5786312491627, 313.71853915886601}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>HeadScale</key> + <real>0.5</real> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3233</integer> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3231</integer> + </dict> + <key>ID</key> + <integer>3227</integer> + <key>Points</key> + <array> + <string>{393.27734031286309, 308.69018471488243}</string> + <string>{391.2600010011621, 313.65891577339352}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>HeadScale</key> + <real>0.5</real> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3233</integer> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>Head</key> + <dict> + <key>ID</key> + <integer>3233</integer> + </dict> + <key>ID</key> + <integer>3228</integer> + <key>Points</key> + <array> + <string>{400.88853753497244, 291.47057979730948}</string> + <string>{398.72236240350077, 296.56014606897668}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>HeadScale</key> + <real>0.5</real> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + <key>Tail</key> + <dict> + <key>ID</key> + <integer>3234</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{413.13675213675219, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3229</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1265 +\cocoascreenfonts1{\fonttbl\f0\fnil\fcharset128 HiraKakuProN-W3;\f1\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 \'8c\'8b\'89\'ca\'82\'aa\'96\'be\'82\'e7\'82\'a9\'82\'c9\'92\'78\'82\'ad\'82\'c8\'82\'c1\'82\'c4\'82\'a2\'82\'e9\'81\'42 +\f1 \ +12 +\f0 \'83\'58\'83\'8c\'83\'62\'83\'68\'82\'c5\'8e\'c0\'8d\'73\'82\'b5\'82\'bd\'8d\'db\'81\'41 +\f1 Java +\f0 \'82\'c6\'82\'cc\'8f\'91\'82\'ab\'8d\'9e\'82\'dd\'82\'cc\'90\'ab\'94\'5c\'8d\'b7\'82\'cd\'81\'41 +\f1 1.30 +\f0 \'94\'7b\'82\'c5\'82\'a0\'82\'e9\'81\'42 +\f1 \ + +\f0 \'83\'56\'83\'93\'83\'4f\'83\'8b\'83\'58\'83\'8c\'83\'62\'83\'68\'82\'c5\'8e\'c0\'8d\'73\'82\'b5\'82\'bd\'8f\'ea\'8d\'87\'82\'c6\'94\'e4\'8a\'72\'82\'b5\'82\'bd\'8f\'ea\'8d\'87\'81\'41 +\f1 12 +\f0 \'83\'58\'83\'8c\'83\'62\'83\'68\'82\'c5 +\f1 2.40 +\f0 \'94\'7b\'82\'cc\'90\'ab\'94\'5c\'8c\'fc\'8f\'e3\'82\'aa\'8c\'a9\'82\'e7\'82\'ea\'82\'e9\'81\'42 +\f1 \ +}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{398.06837606837598, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3230</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{383, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3231</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{406.12820512820514, 296.16521739130428}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3232</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{390.35897435897425, 296.16521739130428}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3233</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{398.06837606837598, 279}, {10.86324786324781, 12.669565217391387}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3234</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + </dict> + </array> + <key>ID</key> + <integer>3223</integer> + </dict> + <dict> + <key>Bounds</key> + <string>{{342, 193}, {123, 60}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>3222</integer> + <key>Shape</key> + <string>Circle</string> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1265 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 tree_name_2}</string> + </dict> + <key>VFlip</key> + <string>YES</string> + </dict> + <dict> + <key>Class</key> <string>Group</string> <key>Graphics</key> <array> @@ -68,8 +476,8 @@ <integer>3211</integer> <key>Points</key> <array> - <string>{356.34543606030172, 308.53288281512982}</string> - <string>{358.52334639036911, 313.24965650249055}</string> + <string>{356.11116157821749, 308.66940440411383}</string> + <string>{358.09063560094091, 313.45599167394289}</string> </array> <key>Style</key> <dict> @@ -103,8 +511,8 @@ <integer>3212</integer> <key>Points</key> <array> - <string>{348.56431748888383, 291.18476239489189}</string> - <string>{351.2055864906597, 296.22711532547004}</string> + <string>{348.34270914528514, 291.33205999856386}</string> + <string>{350.77616074277557, 296.46592473782943}</string> </array> <key>Style</key> <dict> @@ -138,8 +546,8 @@ <integer>3213</integer> <key>Points</key> <array> - <string>{340.76540016591923, 308.41125988727646}</string> - <string>{343.24722775843708, 313.34292542658341}</string> + <string>{340.5389433006477, 308.55561521246977}</string> + <string>{342.81544694650205, 313.57159030244952}</string> </array> <key>Style</key> <dict> @@ -173,8 +581,8 @@ <integer>3214</integer> <key>Points</key> <array> - <string>{334.93249456109351, 308.48751652142602}</string> - <string>{332.62748807512872, 313.31633510986131}</string> + <string>{335.14167308253087, 308.61436510103903}</string> + <string>{333.01836220387491, 313.51548420231512}</string> </array> <key>Style</key> <dict> @@ -208,8 +616,8 @@ <integer>3215</integer> <key>Points</key> <array> - <string>{342.54606680190636, 291.25997668236658}</string> - <string>{340.08455024886598, 296.19744896567033}</string> + <string>{342.75355744338964, 291.39154734355117}</string> + <string>{340.47865028883791, 296.40842905316379}</string> </array> <key>Style</key> <dict> @@ -413,8 +821,8 @@ <integer>3199</integer> <key>Points</key> <array> - <string>{108.92071964681287, 308.76955730605567}</string> - <string>{110.75770821265492, 313.64784567215463}</string> + <string>{109.06833047604893, 308.69275440001746}</string> + <string>{111.01447970492481, 313.49722615446171}</string> </array> <key>Style</key> <dict> @@ -448,8 +856,8 @@ <integer>3200</integer> <key>Points</key> <array> - <string>{101.18795344995119, 291.42641204129848}</string> - <string>{103.49350731612593, 296.65142060307079}</string> + <string>{101.31085077580391, 291.35204046126847}</string> + <string>{103.71694757818067, 296.50283146119637}</string> </array> <key>Style</key> <dict> @@ -483,8 +891,8 @@ <integer>3201</integer> <key>Points</key> <array> - <string>{93.372756742502119, 308.65229707031142}</string> - <string>{95.516430047433317, 313.7598515598155}</string> + <string>{93.503662763117504, 308.57677819728826}</string> + <string>{95.750855006704242, 313.61008609293987}</string> </array> <key>Style</key> <dict> @@ -518,8 +926,8 @@ <integer>3202</integer> <key>Points</key> <array> - <string>{88.042933650729921, 308.55602605513161}</string> - <string>{85.836936530128312, 313.41818275579402}</string> + <string>{88.152295601360677, 308.62048100341337}</string> + <string>{86.037584656368963, 313.52630481935802}</string> </array> <key>Style</key> <dict> @@ -553,8 +961,8 @@ <integer>3203</integer> <key>Points</key> <array> - <string>{95.661140987977674, 291.33448960867088}</string> - <string>{93.306346998937101, 296.31116295515108}</string> + <string>{95.763998745765107, 291.39784133763533}</string> + <string>{93.497823019704398, 296.41975296722126}</string> </array> <key>Style</key> <dict> @@ -747,47 +1155,14 @@ <key>Head</key> <dict> <key>ID</key> - <integer>3193</integer> - </dict> - <key>ID</key> - <integer>3195</integer> - <key>Points</key> - <array> - <string>{393.49998906367091, 253.50001501742494}</string> - <string>{393.49998906367091, 278.49999681519546}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>7</integer> - </dict> - </dict> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> <integer>3166</integer> </dict> <key>ID</key> <integer>3194</integer> <key>Points</key> <array> - <string>{145.50001140135399, 253.50001501742412}</string> - <string>{145.50001140135399, 278.49999681519836}</string> + <string>{145.45435382799056, 253.50000647869865}</string> + <string>{145.41693795363071, 278.50066612099874}</string> </array> <key>Style</key> <dict> @@ -818,336 +1193,14 @@ <key>Head</key> <dict> <key>ID</key> - <integer>3188</integer> - </dict> - <key>ID</key> - <integer>3183</integer> - <key>Points</key> - <array> - <string>{404.12958176855881, 308.65921242132578}</string> - <string>{406.12364005661652, 313.43859392948741}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>HeadScale</key> - <real>0.5</real> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>3191</integer> - </dict> - </dict> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> - <integer>3191</integer> - </dict> - <key>ID</key> - <integer>3184</integer> - <key>Points</key> - <array> - <string>{396.35376840684916, 291.32505538205629}</string> - <string>{398.79684992475075, 296.4532657388113}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>HeadScale</key> - <real>0.5</real> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>3193</integer> - </dict> - </dict> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> - <integer>3189</integer> - </dict> - <key>ID</key> - <integer>3185</integer> - <key>Points</key> - <array> - <string>{388.5521039458219, 308.54763121332167}</string> - <string>{390.83970837630807, 313.55743010016084}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>HeadScale</key> - <real>0.5</real> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>3192</integer> - </dict> - </dict> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> - <integer>3190</integer> - </dict> - <key>ID</key> - <integer>3186</integer> - <key>Points</key> - <array> - <string>{383.22773442246, 308.66303411732099}</string> - <string>{381.17258494295106, 313.60514458829601}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>HeadScale</key> - <real>0.5</real> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>3192</integer> - </dict> - </dict> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> - <integer>3192</integer> - </dict> - <key>ID</key> - <integer>3187</integer> - <key>Points</key> - <array> - <string>{390.83198296208826, 291.43807798208542}</string> - <string>{388.62130964277918, 296.4951642188276}</string> - </array> - <key>Style</key> - <dict> - <key>stroke</key> - <dict> - <key>HeadArrow</key> - <string>0</string> - <key>HeadScale</key> - <real>0.5</real> - <key>Legacy</key> - <true/> - <key>TailArrow</key> - <string>0</string> - </dict> - </dict> - <key>Tail</key> - <dict> - <key>ID</key> - <integer>3193</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{403.13675213675191, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3188</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{388.0683760683757, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3189</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{372.99999999999972, 313.33043478260845}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3190</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{396.12820512820485, 296.16521739130428}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3191</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{380.35897435897402, 296.16521739130428}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3192</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - <dict> - <key>Bounds</key> - <string>{{388.0683760683757, 279}, {10.86324786324781, 12.669565217391387}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>3193</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - </dict> - </array> - <key>ID</key> - <integer>3182</integer> - </dict> - <dict> - <key>Class</key> - <string>Group</string> - <key>Graphics</key> - <array> - <dict> - <key>Class</key> - <string>LineGraphic</string> - <key>Head</key> - <dict> - <key>ID</key> <integer>3161</integer> </dict> <key>ID</key> <integer>3156</integer> <key>Points</key> <array> - <string>{156.117354157287, 308.66598811690199}</string> - <string>{158.10171385541472, 313.45012037448026}</string> + <string>{156.08799256116546, 308.68209565016826}</string> + <string>{158.0493400135307, 313.47816107367669}</string> </array> <key>Style</key> <dict> @@ -1181,8 +1234,8 @@ <integer>3157</integer> <key>Points</key> <array> - <string>{148.34528590039389, 291.33043112783105}</string> - <string>{150.78097495210633, 296.46296823208183}</string> + <string>{148.32403618480234, 291.34380654125698}</string> + <string>{150.7413858868733, 296.48747725315701}</string> </array> <key>Style</key> <dict> @@ -1216,8 +1269,8 @@ <integer>3158</integer> <key>Points</key> <array> - <string>{140.54250106184949, 308.55346170220059}</string> - <string>{142.82199652482811, 313.56775167989719}</string> + <string>{140.51877030171266, 308.56775867607831}</string> + <string>{142.77843552243914, 313.59350602347314}</string> </array> <key>Style</key> <dict> @@ -1251,8 +1304,8 @@ <integer>3159</integer> <key>Points</key> <array> - <string>{135.20708841106685, 308.65154074985202}</string> - <string>{133.13589378013071, 313.58321849338353}</string> + <string>{135.16792797139425, 308.62942531064101}</string> + <string>{133.06577448018848, 313.54235421424795}</string> </array> <key>Style</key> <dict> @@ -1286,8 +1339,8 @@ <integer>3160</integer> <key>Points</key> <array> - <string>{142.81310344334779, 291.42703273046504}</string> - <string>{140.58724492463014, 296.47392848762632}</string> + <string>{142.77764294680048, 291.40601990207904}</string> + <string>{140.52279178917794, 296.43465360870397}</string> </array> <key>Style</key> <dict> @@ -1476,133 +1529,7 @@ </dict> <dict> <key>Bounds</key> - <string>{{342, 176}, {29, 17}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>FitText</key> - <string>YES</string> - <key>Flow</key> - <string>Resize</string> - <key>ID</key> - <integer>8</integer> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - <key>stroke</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Pad</key> - <integer>0</integer> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1265 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs28 \cf0 Tree}</string> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - <key>Wrap</key> - <string>NO</string> - </dict> - <dict> - <key>Bounds</key> - <string>{{337, 193}, {113, 60}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>ID</key> - <integer>7</integer> - <key>Shape</key> - <string>Circle</string> - <key>Style</key> - <dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1265 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs28 \cf0 Oshiro}</string> - </dict> - <key>VFlip</key> - <string>YES</string> - </dict> - <dict> - <key>Bounds</key> - <string>{{94, 176}, {29, 17}}</string> - <key>Class</key> - <string>ShapedGraphic</string> - <key>FitText</key> - <string>YES</string> - <key>Flow</key> - <string>Resize</string> - <key>ID</key> - <integer>6</integer> - <key>Shape</key> - <string>Rectangle</string> - <key>Style</key> - <dict> - <key>fill</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - <key>shadow</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - <key>stroke</key> - <dict> - <key>Draws</key> - <string>NO</string> - </dict> - </dict> - <key>Text</key> - <dict> - <key>Pad</key> - <integer>0</integer> - <key>Text</key> - <string>{\rtf1\ansi\ansicpg1252\cocoartf1265 -\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} -{\colortbl;\red255\green255\blue255;} -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc - -\f0\fs28 \cf0 Tree}</string> - <key>VerticalPad</key> - <integer>0</integer> - </dict> - <key>Wrap</key> - <string>NO</string> - </dict> - <dict> - <key>Bounds</key> - <string>{{89, 193}, {113, 60}}</string> + <string>{{84, 193}, {123, 60}}</string> <key>Class</key> <string>ShapedGraphic</string> <key>ID</key> @@ -1625,7 +1552,7 @@ {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\f0\fs28 \cf0 Daichi}</string> +\f0\fs28 \cf0 tree_name_1}</string> </dict> <key>VFlip</key> <string>YES</string> @@ -1758,7 +1685,7 @@ <key>MasterSheets</key> <array/> <key>ModificationDate</key> - <string>2014-02-04 04:37:01 +0000</string> + <string>2014-02-07 10:01:58 +0000</string> <key>Modifier</key> <string>Daichi TOMA</string> <key>NotesVisible</key> @@ -1839,7 +1766,7 @@ </dict> </array> <key>Frame</key> - <string>{{1008, 396}, {881, 922}}</string> + <string>{{526, 106}, {881, 922}}</string> <key>ListView</key> <true/> <key>OutlineWidth</key>