Hatena::ブログ(Diary)

DebugIto’s diary このページをアンテナに追加 RSSフィード

2016-05-05

Stackageに自分のパッケージを上げる


最近はもうstackとstackageには頼りっきりで、使いたいパッケージがstackageに入っていないとちょっとイラッとくるくらいになってきたが、そういえば自分もいくつかのパッケージをhackageに上げている。大したものではないとはいえ、それらをstackageに載せないのはスジが通らないなと思い、stackageに上げることにした。

さて、自分のパッケージをstackageに上げるにはどうすればいいか。必要なことは以下のページに書いてある。

手順としては、stackageレポジトリをforkして、build-constraints.yamlに自分の名前とパッケージのリストを追加して、pull requestを送るだけだ。

ただし、stackageに入れるパッケージは以下の3点を満たす必要がある(あるいは、満たす「べき」である?)

  1. All packages are buildable and testable from Hackage.
  2. All packages are compatible with the newest versions of all dependencies.
  3. All packages in a snapshot are compatible with the versions of libraries that ship with the GHC used in the snapshot


travisスクリプトビルドエラー対応


第1の条件はこれまで通りきちんとパッケージングしてhackageに上げれば満たされる。

テストに関しては.travis.ymlが提供されているのでこれをサクっと利用するのがいいだろう。

GHC + cabalおよびstackを用いたビルドパターンをいくつかのバージョンでやっている。なかなか良さそうだ。

なお、stackageに上げたパッケージがビルドに失敗する場合、「1週間以内を目安に解決しろ」とのこと。


依存パッケージのバージョン上限問題


第2の条件は、stackageに上げるパッケージが依存するパッケージのバージョン上限に関係する。

例えば、.cabalファイルに以下のようなbuild-dependsがある場合、

  build-depends: foo-bar >=0.3.0.1 && <0.5

foo-bar-0.5がリリースされると第2の条件が満たされなくなる。この場合、foo-barに依存しているパッケージの作者が(1週間以内を目安に)解決しなければいけない。foo-barの変化が小さければ新バージョンでのビルドとテストを確認してbuild-dependsを変更するだけでよい。そうでない場合はちょっと厄介なことになるだろう。

ここで問題となるのは、依存パッケージが他人のものである場合、それがいつメジャーバージョンアップされるか分からないということだ。この問題に対処するために、以下のサービスが公開されている。

このサービスは検索したパッケージの依存パッケージのバージョン上限を調べ、それが現在の最新版をカバーしているかチェックしてくれる。パッケージ検索ではauthorフィールドも検索対象になるので、例えば筆者の場合は

ウォッチすればいい。RSSフィードも吐いてくれるので、こいつをフィードリーダーに突っ込んでおけば速やかに依存パッケージのメジャーバージョンアップに対処できる、はずだ。

なお、PVPには反してしまうが、依存パッケージにバージョン上限を記載しないという考え方もある。この件についてMichael Snoyman氏がブログに書いている。

stackage的にはバージョン上限はあってもなくても構わない、ということだろうか。また、stack sdistとstack uploadには--pvp-boundsというオプションがあり、build-dependsのバージョン下限・上限をいい感じに書き加えてくれるらしい。

個人的には、今のところbuild-dependsのバージョンは自分で管理すればいいと思っている。いろいろ規模が大きくなると破綻しそうな気もするが。


依存パッケージのバージョン下限問題


第3の条件は依存パッケージのバージョン下限に関係する。要は、「GHCバンドルされるパッケージバージョンがカバーされるくらいには下限を広く取れ」ということである。

このことの理由は以下で詳細に説明されている。

"lenient"とは"not as strict as expected"という意味らしい。

例えばあるGHCバージョンにパッケージfoo-bar-0.2がバンドルされており、自分のパッケージのbuild-dependsがfoo-bar >=0.3だとする。すると、バンドルされたfoo-bar-0.2とユーザスペースにインストールされたfoo-bar-0.3が混在する状況になりうる。これが結構ややこしいコンパイルエラーを引き起こし、運が悪い場合は詰む。

さらに言うと、Haskell Platformで提供されるパッケージバージョンをカバーしておくといいようだ。これらは以下のページで確認できる。

ぶっちゃけそれほど多くないので、現状では人力でチェックすればいいと思う。

2016-04-30

Gtk-Uguiss-2.00をリリースした


Gtk2/Gtk3/xfwm4テーマであるGtk-Uguissの新バージョンを作った。

f:id:debug-ito:20160430115553p:image:w600

バージョン1.xx系列はXubuntu 14.04 (Trusty)が、バージョン2.xx系列はXubuntu 16.04 (Xenial)がターゲットである。いろいろ試行錯誤して目に着いたバグは潰したのでリリースした。

なお、そもそもなんでGtkのテーマなぞ作っているかはGtk2/Gtk3/xfwm4テーマを作った - DebugIto’s diaryを参照。

バージョン2.00の主な変更点は以下の2点である。

  • Xfce4.12の新ウィンドウスイッチャへの対応。
  • Gtk3の怒濤の変化への対応。

Xfce tabwin


TrutyのXfceは4.10だったが、Xenialでは4.12になっている。Xfce4.12では、ウィンドウスイッチャ(通称"tabwin")が新しくなり、ウィンドウサムネイルの表示やマウスでのウィンドウ選択が可能になった。

ということで、このtabwin向けの色設定を追加した。

Gtk3の互換性問題


Gtk3は、Trusyではバージョン3.10, Xenialでは3.18になっている。この間、互換性を破壊するものを含む様々な変更が加えられたようで、その対応に追われた。新しく追加されたウィジェットやエフェクトに正常にスタイルが当たらないならともかく、checkboxやspinnerといったごく基本的なウィジェットへのスタイル設定がぶっ壊れているのを見た時には開いた口が塞がらなかった。

Gtk3の連中は後方互換性を維持するつもりがあるのだろうか。あまり好き勝手なことをやっているとユーザ(ここではテーマ開発者)から愛想をつかされ、コミュニティは衰退し、結局自分たちしか使えない何かになり下がりはしないか。実際、Xubuntu 16.04のリリースブログ記事にはこんな文言がある。

Albatross, Bluebird and Orion GTK+ themes have been dropped since they do not support newer GTK3 versions


16.04になってデフォルトのテーマ設定の選択肢が非常に狭まったと感じたが、Gtk3のせいなのだろう。

もちろん、新機能を追加したり既存の問題を解決したりするためには後方互換性を破壊する変更がしばしば必要になるので、なかなか難しいところではある。Gtk3の開発ロードマップがどうなっているのか知らないが、どこかの時点でメンテナンスモードになって、非互換な開発はGtk4で進むようになることを願う。

Gtk3のテーマ開発


Gtk3のテーマ設定は大部分がCSSで書かれているが、自分は以下のような手順で修正を行っている。

  1. gtk3-demo、gtk3-widget-factory、その他のGtk3アプリを使って問題のある箇所を見つける。
  2. その箇所に設定されていそうなCSSクラス名を推測し、テーマファイル(ほとんどの場合はgtk-widgets.css)内を探す。
  3. 修正すべき箇所を同定するため、CSSファイルを書き換えて「マーカースタイル」を設定する。例えば、background-color: redとかborder: solid 3px redとかpadding: 50pxとか、とにかく変化が目立つもの。
  4. マーカースタイルが狙い通りの場所に現れていればそこが修正すべき場所なので、適宜修正する。マーカースタイルが表れていなければ、別の場所を試す。

このように、いわばprintfデバッグCSS版のようなことをやっている。実に効率が悪い。

Web開発であればCSSを修正する作業はもう少し楽なはずだ。ドキュメントの構造はHTMLを見れば分かるし、最近のWebブラウザには超優秀なインスペクタがデフォルトで積んであるので、どこに書かれたスタイルがどう効いているのか一目瞭然である。ブラウザ上でリアルタイムに修正することすらできる。

Gtkにそういうものはないのか?

と思って調べたら、まさにGtkInspectorというものがあるそうだ。

Gtk3.14から利用可能とのこと。gtkparasiteというツールが土台となっているらしい。なるほど、これは具合が良さそうだ。今度なにかあったら試してみよう。もっと早く調べるべきだった。

XfceとGtk3


tabwinのスタイル設定をして気付いたのだが、tabwinを含むXfce4.12のアプリはいまだ大部分がGtk2を使っている。テーマ開発者としては安定しているGtk2を使ってくれる方が助かるが、いつまでもGtk2を使っていていいのかという不安もある。

と思っていたら、開発者のブログにちょうどそういった記事が上がっていた。

どうやらXfce4.14の目標は、大部分のアプリをGtk3にポートすることらしい。ほっとしたような気もするし、余計なことを・・ ともちょっと思う。

まあXfceならそんなにキレッキレのGtk3機能は使わず、無難なウィジェットにおさまることだろう。

2016-04-23

鼻詰まり時の鼻うがい


前回の慢性上咽頭炎の近況で書き忘れていたが、花粉症などで鼻が詰まっている時の鼻うがいについて記す。

当然だが、鼻の通りが悪い状態では鼻うがいもやりづらいし、鼻が完全に詰まっている状態では鼻うがいはほぼ不可能だ。

そのような時にも鼻うがいをやるテクニックとして鍼灸師さんから教えてもらったのが「スクワットをする」ことである。スクワットをすることで一時的に鼻が通るようになるので、その隙に鼻うがいをするのだとか。花粉症で鼻が詰まっている時に実際にやってみたが、確かに心持ち鼻が通る気がした。

他にも、「ペットボトルか何かで脇の下を圧迫すると、その逆側の鼻が通るようになる」というのをためしてガッテンでやっていた。ただしこれは長時間やり過ぎると腕の血流が悪くなるので要注意である。

また、個人的な経験では、朝、冷水で顔を洗ったり髪を濡らしたりした後に鼻が通りやすくなったと思う。逆に、うがいをすると鼻が詰まった。理由はよく分からない。

ただ、本当に花粉症が厳しい時は何をどうしても完全に鼻を通すのは不可能である。完全に鼻が詰まっている時は無理せず鼻うがいをしない方がいい。一応通るが通りが悪いときも、くれぐれも慎重にするべきである。無理に鼻の中に水を押し込むと、予想外の場所に水圧がかかって(多分)危険だと思う。

2016-04-17

GHCにおけるヒープとスタック


先ほど、このような記事をQiitaに書いた。

Haskellを書いていて、再帰関数の終了条件設定をミスって無限ループさせてしまうことが何回かあったのだが、CPUだけでなくメモリも無限に持って行かれ、スワップを使い始めたあたりからキーボードへの応答も著しく鈍くなり、とにかく大変な目にあった。

どうやら再帰関数の実行によってサンクが無限増殖し、そいつがヒープメモリを肥大化させているようだったので、RTSオプションでヒープの上限を与える方法を調べたのだった。

さて、RTSオプションのドキュメントを読むと、以下のような記述があることに気付いた。

  • -Ksize [Default: 80% physical memory size] Set the maximum stack size for an individual thread to size bytes.
  • -Msize [Default: unlimited] Set the maximum heap size to size bytes.

-Mオプションはヒープメモリサイズの上限である。こいつがデフォルト青天井なので、サンクの無限増殖で大変な目にあったのだった。

一方、-Kオプションスタックサイズの上限であり、こいつはデフォルトで(物理メモリの8割という大容量とはいえ)上限が設定されている。

では、ヒープとスタックの違いはなんだろうか?と思って調べてみた。

結論から言うと、どうやら以下のようなことらしい。

  • ヒープはサンク(など)が置かれる
  • スタックはサンクを評価する時に使われる

上記のスレでは定番のfoldlを用いて説明されている。

遅延評価版のfoldlでは以下のように評価が進む。

  foldl add 0 [1,2,3,4]
= foldl add (add 0 1) [2,3,4]
= foldl add (add (add 0 1) 2) [3,4]
= foldl add (add (add (add 0 1) 2) 3) [4]
= foldl add (add (add (add (add 0 1) 2) 3) 4) []
= add (add (add (add 0 1) 2) 3) 4

ここで、add(+)の別名とする(見やすさのため)。

上記で積み上がるaddの列は未評価の式、つまりサンクであり、ヒープに置かれる。よって、例えば

foldl add 0 $ repeat 0

とするとサンクの無限増殖によってヒープが肥大化する。この場合、いくらスタックサイズを制限してもどうしようもない。

さて、foldlの評価ではaddが積み上がったサンクがさらに評価されていくが、ここでadd(というか(+))は正格評価である。よって、

  1. (add X 4)を評価する。
  2. Xを評価する。そのためにaddと4は一旦脇においておく。
  3. Xは(add Y 3)である。これを評価する。
  4. Yを評価する。そのためにaddと3は一旦脇においておく。
  5. ...

となる。ここで、評価を進めるために「一旦脇においておく」場所が(多分)スタックとなる。よって、リストに要素が増えれば増えるほどスタックも深く、大きくなり、そのうち上限に当たって死ぬ。

同様の議論Haskell-cafe Stack, Heap and GHCでもされていた。

ちなみに正格版のfoldl'では以下のように評価が進む。

  foldl' add 0 [1,2,3,4]
= foldl' add 1 [2,3,4]    -- (add 0 1)が評価される
= foldl' add 3 [3,4]      -- (add 1 2)が評価される
= foldl' add 6 [4]        -- (add 3 3)が評価される
= foldl' add 10 []        -- (add 6 4)が評価される
= 10

正格版ではサンクは肥大化しないし、評価も1ステップごとに行われるのでスタックも肥大化しない。よって、

foldl' add 0 $ repeat 0

としてもメモリは食われない。ただCPUがぶん回るだけである。

2016-04-02

慢性上咽頭炎の近況 (3)


前回の近況からおよそ2ヶ月経ったので、ここまでの近況を記す。

ランニング


前回、鼻やノドへのダメージを避けるために河原のランニングを断念するかということを書いた。要は冷たく乾燥した空気にさらされるのが良くないと思ったので、代わりにジムのランニングマシーンで走ることを思いついた。

自分は週1回位しか走らないので、フィットネスクラブやジムは月謝が無駄になるかもしれない。そこで区役所のそばにある公営のジムを調べたところ、会員登録も月謝も必要なく、200円でトレーニングルームを3時間使えるとのことだった。これは良いと思い、最近はそちらに通っている。割と混むことが多いが、十分な運動はできていると思う。

ただ、さすがに最近暖かくなってきたのでもう外を走ってもいいかもしれない。が、最近は花粉という別の強敵に襲われている。

花粉症


今年は2月の中旬を過ぎたあたりから花粉を感じるようになった。

自分はそこまで花粉症が酷くなく、シーズンの初めだけキツいイメージなので普段は薬を飲んでいない。が、今はどのみち週1回耳鼻科に通っているので、オロタジンを処方していただいた。また、耳鼻科の先生曰く、「Bスポット療法は花粉症にも効果があると言われている」とのこと。

花粉症で鼻が弱っているせいか、Bスポットはいつもよりかなりしみるようになった。また、Bスポット後にはものスゴい量の鼻水が出る。30分ほど経つと少し落ち着いてくる。

いろいろな人と話す


職場のいろいろな人と話す機会があり、その時に慢性上咽頭炎についていろいろ説明してみた。残念ながら慢性上咽頭炎の経験者はいなかったが、よく分からない体調不良を経験した人は何人かいた。次のような話を伺った。

  • 原因不明の体調不良があったが、漢方食生活の改善で克服したという人。中医学の専門医にしっかり診てもらい、自分に合った漢方薬を処方してもらったのだそうだ。
  • 走ると腕のあたりにじんましんが出るという人。いまだに出るらしく、原因は不明。
  • 原因不明のじんましんを発症したが、海外出張に行ったらいつの間にか治っていたという人。
  • 食後に異常に眠くなるという体調不良があったが、検査したところテニスのジョコビッチと同じグルテン不耐症であったことが発覚。小麦を食べないようにしたら改善したという人。

それにしても人間の体はまだまだ分からないことだらけだ。

風邪


2016年3月21日(月)の午後から鼻詰まりがひどくなり、鼻呼吸が全くできなくなった。経験がある人はわかると思うが、鼻が完全に詰まるのは本当にストレスがたまるものだ。普段あまり意識していない所作でも口、ノド、鼻、耳の気圧がおかしくなり、下手するとどこか破裂しそうになる。その夜はずっと口呼吸で寝ていた。

翌日(3月22日)の朝起きるとノドが痛く、熱があった。また、ここ最近見ることのなかった粘性の強い緑色の鼻水が出た。いつも通っている耳鼻科を受診し、風邪薬を処方していただいた。その日は一日寝て過ごした。

その後、特に朝に緑色の鼻水が詰まることがあったが、週末(3月27日(日))にはほぼ回復していた。

が、3月29日(火)にはまた少し体調が悪化。緑色の鼻水が出て、また、鼻風邪を引いた時によくある鼻がツーンとする感覚があった。ちょうど去年の6月にノド風邪を引いた時も一旦良くなってからまた酷くなった覚えがある。一体どうなっているのか。結局その週も睡眠を多めに取り、体力回復に努めた。

今回の風邪の特徴的な症状として緑色の鼻水があったと思う。鼻の粘膜的な何かが弱っているのだろうか。そう思い、試しに朝夕やっていた鼻うがいのうち、夕方のターンを一時的にやめてみた。すると、朝の鼻水が少なくなった。鼻うがいとの因果関係はよく分からないが。

症状の状況


この2ヶ月間の症状はだいたい以下のような感じだった。

  • 目まい。平常時はほとんど感じなくなったが、お腹が空いたり、ある程度お腹が空いている状態でお菓子を食べたりすると決まって目まいを感じた。
  • 頭がぼうっとして、光が眩しくなる感覚。液晶モニターを眩しく感じることがあった。これはあまり頻度は高くなく、いつ起きるのかも分からない。

2月初めは症状が少なかったように思うが、花粉症の症状が出てからはこれらの症状がそれなりに出るようになった。ただ、3月に風邪を引いて以降はこういった症状はかなり少なくなったように思う。慢性上咽頭炎が治ってきたからか、花粉が減ってきたからか、それとも暖かくなってきたからだろうか。

とはいえ、一時的に症状がほとんどなくなることはこれまでにもあったと思うので、あまり楽観視はできない。