2013年8月28日水曜日

xmonadとHaskell(その3)

レコード構文

さて、レコード構文の続き。

レコード構文では中括弧の中でプロパティ名の様な名前が定義でき、値を作るときにも

name = "tubasa"

の用に使うことができた。

しかし、実は、このnameはただの名前ではない。

実は、対応する値を取り出すことの出来る関数でもある。
すなわち、その2で定義されたdarekaからnameに該当する値を取り出したい時

name dareka とすると、"tubasa"を返してくれる。
saikyou dareka なら 9999 である。

凄くない??!!

defaultConfig {...}とは何者?

さて、値コンストラクタを使って値を定義する方法を見てきた。
ここで注意深く見ないとダメなのは、defaultConfigは何か?ってこと。


defaultConfigは「d」という小文字で始まっている。
つまり、値コンストラクタではない!!

例えるなら、defaultConfigは


で言うところのOkamaではなくて、darekaに該当する。
そもそも、値コンストラクタを使って、値を作成する場合、引数を省略することはできない。その2のはじめでも紹介した通り、defaultConfigに該当するデータ型の持つ項目(引数)の数は15個あるので、3つだけでは値は作れないのだ。

しかし、、、defaultConfigは中括弧を使ったレコード構文っぽいのを使ってるよ?

これがレコード構文のもうひとつ面白いところで以下のようなことが出来る。

chigau_dareka = dareka { name = "akira"}

これは、darekaで定義されている値を元に、一部分だけを変更した新しい値を作っている。なので、chigau_darekaの中身は Okama { name = "akira", saikyou = 9999 }っぽく出来上がっている。

なので、defaultConfigというのは、既にどこかで中身の各項目の値が設定されて定義された値であり、そのデフォルトの値に対してレコード構文を用いて必要な箇所だけを再設定して、新たな値を作り出しているのだった。

あちこちのxmonad.hsを探索する時、defaultConfig以外でも、このレコード構文である中括弧にはよく出くわす。
はじめ、この中括弧部分と周りの関係がちっともわからなかったので、ネットをフラフラと探索して初心者サイトなんかを見ていたんだけれど、全然紹介されているところを見つけられなかった。
なので、このメモ記事で、xmonad設定の取っ掛かりになるといいなと思う。

わかってる人はわかってるんだと思うけれど、単語の始まりが大文字か小文字かに注意することで、それが既に定義された何かか、値コンストラクタかを見分ける事が出来るだけでも、設定ファイルを読んでいく時のコツになると思う。

GHCiで試す

一応、GHCiもメモ
ターミナルからghciで起動。:qで終了。
スクリプト書いた時は、:l ファイル名(.hs拡張子はいらない)で読み込んで:rで再読み込み。

:m XMonadとかするとXMonadモジュール読み込む。

式の型を知りたい時は:t
話題のdefaultConfigは
:t defaultConfig
defaultConfig :: XConfig (Choose Tall (Choose (Mirror Tall) Full))
  -- Defined in `XMonad.Config'

XConfigうんたらかんたら型という型でした。

2013年8月27日火曜日

xmonadとHaskell(その2)

設定してみる


これを見れば、少し何かのプログラムをしたことがあるなら、Haskellを知らなくても、{}の内部でキーワードに対応して何かを設定していることがわかる。

実際に、teriminal =の右側の文字列を、"xterm"とか"gnome-terminal"とか自分の持っているものに変えてみる。

modMask = の右側には mod4Maskを指定してある。これは、ウインドーズキーに割り当てられている。デフォルトはmod1Maskでaltキーに割り当てられている。

設定を変えた後は win + q で新しい設定に更新される。



ここで、xmonadの設定の基本の一つは、簡単に言えば、この{}の中にある各項目を設定していくことにある。


上の例のxmonad.hsには3個の項目しかないが、設定すべき項目は全部で15個の項目がある。上の例で設定されている項目の値らしきものは、文字列やシンボル、数字なので初めて見た人でもわかるが、この他の項目には、何を言ってるのかわからない値もみられる。

/usr/share/xmonad-0.11/man/xmonad.hs

上のファイルには、すべての項目のデフォルトの値が示されているかもしれない。



改めて、構文をみてる。

main = xmonad defaultConfig { .... }

これは、xmonad関数に「defaultConfig {...}」で示される値を引数として渡すことを定義している。

defaultConfig {....} は一つの値を示している。


値ってなんだろう?

よく見る、値って"xterm"とか、mod4Maskとか、3とか普通に値っぽく見える。

しかし、Cなんかの構造体やら、Javaやrubyのオブジェクトやらでは、いくつかの要素をひとまとめにして一つのものとして扱えたりする。例えば、「名前」、「性別」、「体重」の3つが纏まって、ひとつの「人間」という値を表したりする。

そしてこれは、単なる"xterm"よりも、なんだかちょっとかっこ良いオブジェクト指向チックで複雑な値にもみえる。

でも、よく考えてみれば、「人間」を表す時に「名前」のみで構成されていれば、単なる"xterm"な値と変わらない。要素がひとつからなる値の方が特殊なのかもしれない。


Haskellの「型」

Haskellにも見慣れた「型」がある。
整数を表すInt、実数を表すFloat、文字を表すChar、真偽値を表すBool。

また、自作の型を定義することが出来る。
Bool型の定義で構文を大まかに例示すれば以下の通り。

data Bool = False | True
 dataキーワードに続けて「型名」を書く。ここではBoolが「型名」

そして、イコールの右側に、取り得る値の種類を定義する。|(縦棒)を使って「または」としてどんどん繋げる。つまり、Boolは「False」っていう値の種類、または、「True」っていう値の種類をとる。

ここで定義されているFalseは「値」そのものではなくて、「値の種類」であることに注意。そして、これを「値コンストラクタ」と呼ぶことを覚える。


コンストラクタは、インスタンスを作るときのアレだ!
すなわち、値コンストラクタっていうのは、値を作る関数と同じ物の事。

ここで、さっきの「人間型」を定義してみる。

<その1>
「人間」を表すのに「性別」っぽいもので、値の種類を分けてみた。
「男」、「女」、「男の娘」の3種類

data Human = Otoko | Onna | Okama

種類分けだけだと、False、TrueのBool型に似てる。


<その2>
しかし、実はOtoko、Onna、Okamaは関数なので、 引数を取ることが出来る。
なので、実は以下のような定義が出来る。
「男」を構成する要素として「名前」をString、「度胸」度をIntで表す。
「女」を構成する要素として「名前」をString、「愛嬌」度をIntで表す。
「男の娘」を構成する要素として「名前」をString、「最強」度をIntで表す。

data Human = Otoko String Int | Onna String Int | Okama String Int


これを踏まえて、もういちどBool型の定義に戻ってみる。
data Bool = False | True

他の言語で見慣れたFalseやTrueは値そのものを示すリテラルなシンボル的なものかもしれないけれど、Haskellの世界ではFalseもTrueも引数を取っていない値コンストラクタであり、それは引数が0個の関数である。
なので、値とは、Falseそのものではなく、そのコンストラクタの評価結果であると考える。

そうそう、最後に約束事として、型名も値コンストラクタも大文字で始まらなければならない。

値を作る

これまでは型を定義する話。
実際に定義された型の値は次のように作る(定義する)。

hoge :: Bool
hoge = True

なんだよ、結局、書き方は他の言語でみてるのとおんなじじゃん!!とか言わない。
Trueは値コンストラクタで関数。

上記の式は、「hogeという変数に、Trueを代入」しているように見えるが、Haskellではそうではないらしい。「純粋関数型プログラミング言語」っていうのは、まだよくわからないけれど、同じものに対する関数の結果はいつも同じであるはずなため、中身が変わることを意味する「変数」とか中身を入れ替える行為になる「代入」とかいう概念がそもそも無さそうな感じ。

では、Haskellな人はどう読んでいるのか?
「hogeをTrueと定義する」みたいな感じ。

何が違うの?じゃなくて、まずは、そう感じるんだ!と心の中で唱える。
じゃ、変数じゃない「hoge」ってなにかといえば、単なる「名前」。小文字ではじまってるのは、何かを表す「名前」なのだ。
「hogeってのはBool型の何かだよ」っていって、Bool型のTureが示す値で定義してる。

まぁ、「=」があると 何かを「代入」じゃなく「定義」してるって思えるようになる努力をするとHaskellが理解できるようになるといいなって思ってる。


それはさておき、次に、人間を作ってみる。

dareka :: Human
dareka = Otoko "taro" 10

なんとなく、人間っぽいのを作ってる感じのする式になった。

しかし、"taro"が名前で、10が度胸度を表しているとは一見してわからない。
Haskellの型の場合上で見たように、単に値コンストラクタとそれに続く引数の位置
によって、要素を識別することになる。

 一方、オブジェクト指向言語の場合、要素についてはプロパティとして、その名前がついていて値との関連性が分かりやすい。


つまり、

name = "taro"
dokyou = 10

とかいう分かりやすい書き方がHaskellにはないのかな、、、、ってどっかでみたような?

terminal = "urxvt"
modMask  = mod4Mask

忘れてたかもしれないけれど、これの話をしてたんだよね。

型の定義「レコード構文」

型の定義において、先に書いた構文とは別に、値コンストラクタが複数の引数を取る時、その引数が何を表すのかわかりやすくするための構文、「レコード構文」がある。

型の定義において、値コンストラクタの引数部分に中括弧を用いて、その中に、要素の名前を定義する。
値として定義する時には、値コンストラクタの引数部分に中括弧を用いて名前に対して「=」を使って要素となる値を定義する。

この、オカマの最強度9999を持つつばさちゃんは、xmonadの設定defaultConfigと同じようにみえる。

つまり、逆に言えばdefaultConfig {...}は、やっぱりこれでひとつの値なのだ。


2013年8月25日日曜日

xmonadとHaskell(その1)

インストールとか


・本体
archlinuxの場合、xmonadxmonad-contribパッケージをインストール。
haskell諸々は依存関係で勝手にインストールしてくれる。

・それ以外
xmonadそのものには、他のウインドマネージャで、画面の上や下にあるステータスバーとかパネルと呼ばれるものが無い。なので、別途、好みのものを用意する。

ツールバーそのものが、dzen2やxmobar。
そして、dzen2を選択すると、これはそれほど賢いものでは無くて、主な機能は、単に与えられたテキストを表示するだけのものなので、システムの情報を表示したい(CPU使用率、メモリ使用率、ネットワーク使用状況等)なら、自分で情報を得て、それをそのツールバーに渡すことになる。なので、この情報収集のためにconkyを使う。
また、プログラム呼び出し用のメニューがdmenu。

うちでは、xftフォントを使うために

dzen2-git(aur)
conky
dmenu-xft(aur)

辺りをインストール。

xmonadの導入解説にはどこもパネルの作成の紹介があるし、ここのカスタマイズで結構を頭を悩ませるのだけれど、これ自体はあんまりxmonadとは関係ない。そして、パネルについては他の選択肢として、xfce4-panel等、高機能なパネルだけ呼び出して使うとか、DEとの連携をしてパネルはそっちに任せることも出来るらしい。アプレット等が使える派手で高機能なのがお好みなら、dzenの設定をガリガリ書くよりも、あるものを使ったほうが良さげ(by 2ch タイル型WMスレ)

起動

.xinitrcとか起動スクリプトで

exec xmonad

する。
startxで直接、displayマネージャーでも、xdmやslimの場合は上記でOK。

kdmやgdmの場合のヒントは以下(セッション選択のファイルを作る)
2.3 How can I use xmonad with a display manager? (xdm, kdm, gdm)

うちの~/.xsession



DEを使っていればいらないかもしれない、昔ながらの最低限の設定。
xmonad自体でカーソルを制御しないので、xsetrootで調節。
壁紙も設定。fehが定番っぽいけど、デュアルスクリーンでもうまく設定できるNitrogenが便利。

xmonadに関係ないけれど、コンポジット系統(ウインドウを透明にしたり、影つけたりできる)は、バグの少ないCompton(xcompmgrからの派生)が良いらしい。
また、xrandrのデュアルスクリーンもxmonadで使える。


そんな感じで、起動すると何にもなくて寂しいxmonadが立ち上がる。(もしかしたら、真っ暗で立ち上がってるのさえわからないかもしれない)

alt + Shift + Enter で、xtermが立ち上がる。

alt + Shift + q で、xmonad終了。

設定ファイル ~/.xmonad/xmonad.hs

というわけで、いよいよHaskellに対面!
xmonadの設定ファイルとして~/.xmonad/xmonad.hsを以下の内容で作ってみる。

これがxmonadの設定ファイルで、はじめてのHaskell
urxvtが3つ立ち上がってるところ。まだ、パネル等の飾りはありません。


<<追記>>
xmonadとHaskellについてのメモが長くなったので目次を追記

xmonadとHaskellのメモの目次



2013年8月24日土曜日

xmonadとHaskell(その0)

ウインドマネージャを少し前にawesomeからxmonadに変えてみた。
http://xmonad.org/


xmonadはHaskellという言語で動いているんだけれど、このHaskellって言語は、以前から「わけわからん」っていう評判をなんとなく聞いていた。

Haskellで書かれている設定のsampleになる基本的なファイルを見ても構文がパッと見では、イマイチよくわからない。それでも、いくつもの設定の例を見つつ、xmonadのページのリファレンスを見ているとなんとなく設定だけは出来るようになった。

でも、「lispよくわからんけどemacsの設定は適当に書いてる」的な感じよりももっと心もとないため、せっかく色々と楽しくできそうなのに、設定のアレンジを自分ではできないのがもどかしい。

そこで、Haskellの本を買ってきて読んでみた。やっぱ難しくて、眠くなることしばし。でも、はじめてオブジェクト指向の概念に触れた時にように、今まで考えたことのない見慣れないもの、使ったことのない思考回路を刺激されるのは楽しい。

本の中では、一般的な問題の解決をプログラミングの例とかをコンソール上でやるんだけれども、出来るならXmonadを使って遊ぶほうがきっと面白いし、親しめるに違いない。

考え方が整理できたら良いなというメモ。