トップページに戻る

AUTHOR: schwarz1009
TITLE: Haskellについて
BASENAME: 2020/09/16/162218
STATUS: Publish
ALLOW COMMENTS: 1
CONVERT BREAKS: 0
DATE: 09/16/2020 16:22:18
CATEGORY: Haskell
CATEGORY: Webブラウザ
CATEGORY: 英語

関数型ってこういうことじゃないかという仮説

今日は、作業所で仕事がなかったので、
英語の読み上げソフトでHaskellのチュートリアルを聴いていた。
通常、変数は以下のように上から下へと順序的に書いていく。

x = 30
y = x + 10

しかしながら、Haskellでは変数がimmutable(不変)であり、
一度名前付けされた値がプログラムのどの位置であっても変わらないため、
記述を逆にできる。

y = x + 10
x = 30

このプログラムを、じっと見てほしい。
そう、気付くことがある。
これはまさに、関数の引数定義と呼び出しと同じである。
たとえば、C言語では関数は以下のように宣言・定義する。

#include <stdio.h>

int add(int x);

int add(int x) {
    return x + 10;
}

int main() {
    int y;
    y = add(30);
    printf("%d\n", y);
}

Haskellではこうなる。letを使う場合(GHCiから実行):

let x = 30 in x + 10

あるいは、関数を定義する場合(以下は全てファイルから実行):

add x = x + 10

main = print (add 30)

あるいは、単にCと逆向きに書く場合:

main = do { print y }  -- doブロックで複数のアクションの実行が可能

y = x + 10
x = 30

doブロックは;でそれぞれのアクションを区切るか、
レイアウトと言ってインデントを揃えることで
Pythonのようにきれいに書くこともできる。
そして、whereを使うことでこのようにも書ける:

add = x + 10
  where
    x = 30

main = print (add)

そう、ここには、変数と関数の区別もなく、
順序通りに宣言・定義されるという決まりもない。
まさに、プログラミングは関数である。
そして、関数は変数であり、言うとすれば「計算」である。
計算においては、関数もステートメントも変わらない。
これが、Haskellの本質ではないかと僕は思う。

リストとパターンマッチング

公式にあるオンラインのWebブラウザ上でHaskellを実行できる、
Try Haskellで「help」を実行してチュートリアルを一通りやった。
リストとパターンマッチングはとても面白い機能だと感じた。

モナド

Haskellは、「同じ関数を同じ引数の呼び出しで行うと必ず同じ結果が返る」という、
純粋関数型言語であり、
変数はimmutable(不変)である。
しかしながら、変数が不変だと不便なことがある。
特に、IOなどのデータ処理をどうするのか、という問題である。
Haskellでは、「モナド」という圏論のアイデアを使った考え方を用いて、
参照透過性を壊すことなくIOを実現している。
標準的によく使われるListや、
Maybeなどもモナドで実装されている。
モナドの解説はネット上にあふれているので
それを参照してほしい(僕はまだ理解できていない)。

日本人は英語を読むスピードが遅い

日本人がなぜ英語を話せないのかというと、
単純に「読むスピードが遅い」からである。
ネイティブの発音を聞けば分かるが、
ネイティブはとても速く英語を話して理解する。
彼らは、「高速に英語を理解するエンジン」が既にあって、
そのエンジンに乗せて「レールの上を走るように」英語を聴く。
しかしながら、日本人は馬鹿ではない。
英語が速く話せる理由は、英語には意味が少ないからである。
日本語は、意味が多いため、理解するのに時間がかかる。
英語は意味が少ないため、理解するのに時間がかからないのである。

守るべきこと

守るべきことは、ひとつ。
それは、「自由を奪わないこと」である。
これは神との約束である。
自由を奪わなければ、この世界は救われる。

ウィンウィンの外交協力を

菅新総理、誕生おめでとう。
僕が菅に望むことは2つ。
それは「日本のために外国が貢献してくれる外交」と、
「デジタル化をもっとセキュリティや安全の目線から行う」こと。
菅さんは外交が苦手で、
地球儀を俯瞰する安倍前首相に比べて、
外交で知られていないというが、
方針が全くないのであれば、
僕は日本のために外国が貢献してくれる外交をしてほしい。
日本が外国に協力する、というだけではなく、
日本がその国に協力することで相手が日本に貢献し、
外国にとっても利益があるような、
「ウィンウィンの外交」をしてほしい。
単に「仲が良い」というだけでは、
安倍とトランプぐらいの「仲良しの友達」になる。
たとえば、GAFAの最巨頭で知られているGoogleは
アドセンスという広告サービスで大きくなったが、
Webサイトの管理者はGoogleの広告を掲載することで、
Googleからお小遣い程度のお金を得ることができ、
多くのWebサイトがGoogleの広告を掲載するに至った。
このように、たとえばロシアであれば、
ロシアの主張に妥協し、ロシアがやることに納得するだけの
「妥協ロシア外交」をさせられるのではなく、
ロシアと協力することで、日本に利益があり、
協力するロシアの側にも利益があるような、
そんな外交ができればいいと僕は思う。

デジタルはセキュリティと安全を

また、菅と新閣僚によるデジタル推進で強力な競争力を得ると
みんな言っていて、
特にテレワークやオンライン授業が上手くいくだろうと言うが、
僕はセキュリティや安全面で成果をあげてほしいと思う。
特に、オリンピック開催国となる日本では、
オリンピックのためのサーバがセキュリティのリスクにさらされるだろう。
セキュリティと安全は、IT技術においてもっとも大きな課題のひとつである。
安全なインフラを上手く築いてほしいと思う。

最高の国になるか、必然的に破綻するか、どちらか

また、僕は日本の新時代は少し難しいと思う。
なぜなら、最高の国になる要素も多いが、
必然的に破綻する要素も多いからである。
何もない普通の時代にはならないだろう。
最高に栄えるか、最悪に滅びるか、どちらかだ。
全ては劇的に良くなっており、
「今までの人類とは比にならないほどの高度な進歩」がある一方で、
同時に温暖化やトランプ・中国など多くのネガティブな要素がある。
本当に良くなるとしたら、
ネガティブな要素をポジティブな要素に転換し、変えていくことだ。
もし、菅が今までの総理大臣とまったく同じ
「何も変わらない政治」を継承するのであれば、
ポジティブな要素は花開くことなく、
ネガティブな要素にコロナなどさらなるネガティブ要素が増していき、
この国は滅亡するだろう。

破壊ではない手段で世界を変えられるか

また、僕は菅について、少し思うことがある。
彼は、「破壊」には向いていないが、「停滞」もしない。
おそらく、破壊ではない方法で、着実に事をしっかりと進めていく。
そのようなことが得意な政治家ではないかと思う。
破壊ではない手段で世界を変えていくことができるか、
積み上げたものが消え去らない形で人々と共有できるか、
支配ではない方法で社会を「自助」の社会にできるか、
そうした点が成功と失敗を分けさせるポイントではないかと思う。

菅の会見

菅の首相就任会見を見て思うことは
いくつかある。
まず、今までにやったことを継承する、
ということを言いたいせいで、
新しいことをやるというよりも
今まで過去にやったことの紹介になっており、
まるで「自分の手柄話」になっている。
「過去からの継承」に目を向けすぎて、「未来」がない。
また、内容について言えば、
「やるべきことを推し進めるためにどうするか」という内容である。
当たり前でないことを当たり前としないとか、
悪しき前例主義を撤廃するとかは、
「トップダウンに権力が推し進めるための方法論」であり、
まさに官房長官の立場の主張である。
しかしながら、菅にはいいところがたくさんある。
デジタル化をマイナンバーで推し進めるのは自分は賛成だし、
国民が頼りにしてくれるような国家を作るというのも良い。
「帝王」ではなく「縁の下の力持ち」である、
そしてそれでも「奴隷」ではなく「指導者」である、
そのために「臨戦態勢で推し進めていく」、
そのような、
「ビジョンと主張や意見には欠けているが
正しい姿勢と全力ですべきことはする意欲はある指導者」だと感じた。
まさに官房長官の会見であった。

菅はやるべきことをやっていく

菅のいい点は、「やるべきことをやっていく」ということ。
本人は、それしか言っていない。
やるべきことを、安倍を継承してやっていく。
頼りにはなるかもしれないし、今まで通りで楽かもしれないが、
「何一つ新規性がない」。
将来に期待はできるが、スピーチとしてはつまらない会見だった。

政治家に良い人材がいない

また、僕が思うに、今の政治家には「良い人材がいない」のである。
課題の種類が多すぎて、
とても総理ひとりだけでは把握して解決できないほど、
たくさんの問題があるというのに、
その問題を全てくまなく解決できるほど、
人材がそろっていない。
温暖化、コロナ、沖縄、拉致、復興、いくらでも問題はあるのだが、
そうした全てのことを、
菅がたったひとりでいつもの官房長官のように行うと、
いつか無理がでてきて、破綻する。
だからといって、そうした
「困難な問題を解決できるスーパー超人」はそんなにたくさん存在しない。
それこそ、政治家に有能な人材が居なさすぎる。
彼らがどんなにデジタル化を頑張っても、
マイクロソフトやアップルのような超スーパー企業は現れない。
目指しているからといって、
国の社会秩序の維持にも、
行政などの社会制度改革にも暗雲が立ち込める、
そんな政権になったと思う。

ブラウザは抽象的なデータ型を作れば作れるはず

僕が思うに、
WebブラウザのHTMLレイアウトエンジンは難しくない。
たとえば、あるタグを引数として、
そのタグがどのようにレンダリングできるかをデータ型で返す関数を作る。
このデータ型には、
CSSのまだかかっていない「BeforeCSS」クラスと、
CSSをそれにかけた状態である「AfterCSS」クラスを作る。
そして、CSSがかかっていない方のデータ型は、
とても抽象的な「どんなHTMLタグの指示がどういう木構造でされたか」を判断し、
内部にHTMLからパースしたツリー構造(すなわちDOM)を作る。
これに対して、CSSがかかっているデータ型は、
実際のレイアウトエンジンが表示する「どう表示するか」を判断し、
内部にベクトル画像と表示設定(幅を100%にするなど)を含めて、
グラフィックス全体を重ね合わせたグラフィックス構造データを作る。
最後にこのベクトルデータをウィンドウの状態、
すなわち今ウィンドウの幅が1200pxになっているなどの状態に
適合させて表示させればいい。
このウィンドウクラスはウィンドウのさまざまな操作に応じて反応し、
またJavaScriptでイベントやDOMの操作が行えるように、
特定の命令にも反応して、
必要であればDOMのリアルタイムパースや
ペイント処理・レンダリングとも連携するようにする。
難しいのは、HTMLやCSSやJavaScriptのパース処理。
パースを行うために、きちんとしたインタプリタの実装が必要。

Javaの勉強がしたい

僕は、Javaの勉強がしたい。
思い切って言えば、
小さなブラウザのレンダリングエンジンのようなものを作ってみたい。
それも、オブジェクト指向やJavaの応用技術をふんだんに使って、
綺麗な設計と柔軟なシステムによるレンダリングエンジンを作ってみたい。
全体のプログラムの制御内容としては、
HTMLファイルを読み込んで、
それをタグごとに解析し、
パース結果をDOMツリーに変換する。
それをCSSを用いてレイアウトに変えるために
DOMツリーの要素をひとつひとつ、
CSSに基づくレイアウトへと変換していき
最終的に今のブラウザの情報に基づいてペイントする。
そして、コールされた命令に基づいて、
インターネットからHTMLや必要なファイルをダウンロードしたり、
リンクやナビゲートを行う「ネットワーク推移」の機能をつける。
これらをJavaで作ることは、かなり難しいと思う。
まずはこれらをモジュールごとに分割して、
ひとつひとつの機能が成立し、働くように開発してみたい。

必要なコアルーチン

コアルーチンとしては少ない。
まず、どんなタグでもトークンと構文から解析し、
ツリーのデータ構造に「追加」していくルーチン。
このルーチンは、
・HTMLファイルの読み取り
・正規表現を用いたタグ(はじめから終わりまで)の取得
・ひとつひとつマッチしたタグからタグ名と要素と属性を取り出し
・タグ名に応じて要素と属性の意味を解析する分岐ルーチン
・全てのタグを適切にDOMツリーに構造的に追加
となる。
次に、CSSとレイアウトのルーチン。
・CSSの読み取り
・CSSの要素と属性のハッシュ化
・DOMツリーをループしながらひとつひとつCSS適用
・DOMに適用されたCSSに基づいて再帰的にレイアウト
レイアウトを行う上で、
・位置(絶対位置や相対位置の計算も含む)
・大きさ
・色
・フォント
・線
・背景
・余白
・GUIツールキットを用いたボタンやフォーム
・グラフィック効果
などの表示が必要であり、
このためには、
・レイアウト計算や属性適用をセレクタごとに管理
・表示をどのようなレイアウトで表示するか(block, inline)
・相対位置と絶対位置やサイズの計算
・重ね合わせの計算
・画像や色のついたボックスの表示場所の決定
・テキストの表示場所の決定
・ひとつひとつの値を計算
・最終的なレイアウトを計算
などが必要である。
そして、ウィンドウとペイントのルーチン。
・ウィンドウの情報を取得
・ウィンドウのさまざまなフラグに基づいてペイント結果を生成
・ペイント結果をOS固有のグラフィックスに変換
最後に、ナビゲーションのルーチン。
・ダウンロードルーチンにダウンロードすべきファイルを指示
・ファイルのダウンロード
・ボタンやリンクをクリックした時にナビゲート
・HTTPリクエストとレスポンスに基づくサーバとの対話
また、必要なのはこれだけではなく、
JavaScriptインタプリタが必要であり、
これには、
・JavaScriptソースコードの解析(字句解析と構文解析)
・中間言語(三番地コードを用いる)に変換して最適化
・状態ベースの仮想マシンで動く機械語のオブジェクトに変換
・JavaScriptの基本言語APIを提供してリンク
・DOMツリーへの操作のためのAPIの提供
・イベントに応じてJavaScriptの関数をコール
・実際のブラウザのレイアウトに反映
などがさらに必要になる。
Javaで書くのであれば、
これらを上手くクラス図にして、
データ構造とアルゴリズムをひとつひとつ決定し、
クラスとオブジェクトの関係にすれば、
ブラウザのレンダリングエンジンは開発できる。