北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

GHCi上でpiと打てば円周率が表示されるという話

裏書きに残りっぱなしになってたのを書いておく。GHCI上で pi と打つと、πの値が表示できる。

Prelude> pi
3.141592653589793

Pythonだとそうはいかない。

>>> pi
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'pi' is not defined
>>> from math import pi
>>> pi
3.141592653589793

つまり、Haskellではグローバルな名前空間pi が出ているように見えるということ。これはなかなか気持ち悪い。

pi の正体を見てみよう。

Prelude> :i pi
class Fractional a => Floating a where
  pi :: a
  ...
        -- Defined in ‘GHC.Float’

Floating 型クラスに定義されているようだ。 Floating 型クラスは Prelude モジュールに含まれているので、 import などしなくても名前にアクセスできる。なるほど。

さて、拙著 Haskell入門 にも書いたが、この型クラスは浮動小数点数を意味する。この型クラスには pi 以外に、一般的な数値計算で必要な explogsin などの関数も入っている。代表的なインスタンスDoubleFloat

Prelude> :i Floating
class Fractional a => Floating a where
  pi :: a
  exp :: a -> a
  log :: a -> a
  sqrt :: a -> a
  (**) :: a -> a -> a
  logBase :: a -> a -> a
  sin :: a -> a
  cos :: a -> a
  tan :: a -> a
  asin :: a -> a
  acos :: a -> a
  atan :: a -> a
  sinh :: a -> a
  cosh :: a -> a
  tanh :: a -> a
  asinh :: a -> a
  acosh :: a -> a
  atanh :: a -> a
  GHC.Float.log1p :: a -> a
  GHC.Float.expm1 :: a -> a
  GHC.Float.log1pexp :: a -> a
  GHC.Float.log1mexp :: a -> a
  {-# MINIMAL pi, exp, log, sin, cos, asin, acos, atan, sinh, cosh,
              asinh, acosh, atanh #-}
        -- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’

pi が定数ではなく型クラスのメソッドになっているのは、恐らく FloatDouble で多相的に扱いたいからであろう。 GHCの実際の定義 は、以下。お、おう、といった感想。浮動小数点数だから、リテラルに小数点を何桁まで書いたかは精度とは関係ないってことだろう。結局は親の型クラスが持つ fromRational を使って処理される。

instance  Floating Float  where
    pi                  =  3.141592653589793238

instance  Floating Double  where
    pi                  =  3.141592653589793238

一応、ghci上で違いを見ておく。

Prelude> pi :: Double
3.141592653589793
Prelude> pi :: Float
3.1415927

もう一つ疑問が残るのは、数ある数値系の型クラスの中で、なぜ Floating というより具体性の高い型クラスに pi が定義されたのか。 Floating に定義されている関数は、実数値上に定義される関数である。Haskellでは、有理数Fractional 型クラスで表現されている。しかし、当然ながら実数値を正確に表現できる型はない。そこで、コンピュータが一般的に用いる浮動小数点数にこれらの関数を定義した、ということだろう。

最後にまとめると、 pi については以下となる。

  • Prelude に定義されているので、識別子 pi でアクセスできる
  • メソッドになっているため、 FloatDouble で多相的に扱える
  • 実数という型がないので、浮動小数点数上の演算としているのだろう

自分の開発環境用Vagrantfileを作った

qiita.com

ubuntuのインストール作業に勤しむ意味はないので、vagrantに任せることに。

ということでWindows上でvagrant使うことに決めたのだけど、Surface StudioとSurface Book 2の両方で環境構築するのはダルいので Vagrantfile 作って上げた。

github.com

最近はデフォルト厨なので Vagrantfile なんて要らんかなと思ったのだけど、細かい調整でハマって時間を潰してしまったりしたので、まとめることにした。細かい点とは、例えば以下の通り。

  • stackapt で入れない (コマンドを覚えられないのでググるのがめんどい)
  • init.elintero の設定をググらないと書けない
  • libtinfo-dev 入れないと intero が動かない
  • LC_ALL 指定しないと shell が日本語を受け付けない
  • .tmux.conf を適切に設定しないとキーバインドで俺が死ぬ
  • その他、今は忘れている暗黙知をこのリポジトリに集めて二度と同じハマり方をしないようにする

Windows 用にしているけど、OS Xでも使えるはず。とはいえ、OS X上ならVM使わずにローカルに開発環境作る気がする。

WindowsのreaderアプリがEdgeに惨殺される

Windowsreaderアプリが2/15で使えなくなるとのこと 。騒いでいる人がほとんどいないけど、Surfaceタブレットモードで使ったときの相性が非常に良かったので、どうしてそんなことをするのか全く理解ができない1。これでSurfaceを使う理由が1つなくなってしまった。

2/15までサポートされるということになっているが、readerアプリを立ち上げると画面上部がメッセージで専有されてUIがぶっ壊れるので、もうすでに使い物にならない。スクリーンショット取るのが億劫だったのでTwitterから拝借。

が、代替を探したところ、幸い Pico Viewer が要件を満たしてくれることがわかった。使用頻度が高かったサムネイルを一覧するビューがないのだけは残念だが、それ以外のタブレットモードの閲覧に関しては reader とほぼ同じ使い勝手、いや、それ以上使い勝手なので、十分満足できる。価格も財布に優しい。もし、代替品に困っている人が居たら試してみて欲しい。


  1. Edge使わせるため、というのは明白だけど、思考が短絡的過ぎる。

Haskell入門の10章をDocker化する

Haskell入門 の10章は、 SQLite への依存があったりして Windows で試すのは若干面倒だったので、 Docker for Windows で試せるようにした。

https://github.com/hiratara/Haskell-Nyumon-Sample/compare/docker/chap10

docker/chap10 ブランチを持ってきて、Docker for Windows が動いている環境でこんな感じで動かせる。

$ docker-compose build
$ docker-compose run --rm --service-ports weight-recorder

# ソースをいじって stack build したいとき
$ docker-compose run --rm weight-recorder build weight-recorder

docker hubに stack dockerコマンド用のイメージがある ので、LTSが一致しているものを持ってきてベースイメージにしている。なお、残念ながら stack dockerコマンドはWindows非対応 なので今回の目的には使えない。

Windowsで作業ディレクトリを単純にバインドマインティングすると、

Installing executable(s) in
/work/.stack-work/install/x86_64-linux/lts-8.24/8.0.2/bin
/work/.stack-work/install/x86_64-linux/lts-8.24/8.0.2/bin/.copyFile5117023052084420925.tmp:
copyFile: hardware fault (Input/output error)
Completed 2 action(s).

のように微妙なエラーが出たりすることがあるので、 docker-compose でデータボリュームを作ったりしている。後、何も考えずに Docker 化すると、docker-compose build 時の stack の初期化が時間がかかりすぎてあまりにも辛いので、キャッシュが働くように COPY 前にある程度パッケージをビルドするようにしてたりする。

後、かんたんのためにDBを作業ディレクトリに置いていたのがきつくなったので、軽く手を入れて環境変数から指定できるようにした。 /data 以下にDBを置いている。

Surface Book 2 15” を買った

去年 と同様に、今年は Surface Book 2 15”個人輸入した。 MS製品の個人輸入は3度目 1 で、毎年年末の散財の恒例行事となりつつある。

誤解のないように書いておくと、Surface Book 2は 国内でも販売している 。ただし、 15” はUSのみでの販売であるのと、US配列も国内では手に入らない。

15” は フルパワーだと電源につないでいてもバッテリーが減る という問題はあるものの、実用上そんなに困ってはいない。ゲーミングでむしろ邪魔になるのは高温でパワーが抑制されてしまう方で、これは結構頻繁に遭遇する。ので、ゲーミングに使うときは設定は低めの設定で使っている。PUBGも設定さえきちんとすれば快適に遊べる。

f:id:hiratara:20171211085147j:plain

今回のSurface Book 2の事前予約で、MSはいろいろとしくじっている。 redditでは事前予約したのに来ないという悲痛な叫び が多数投稿されている。キャンセルも受け付けてくれず、発送されたとしてもマイクロソフトからは今回の注文に関して何もメールが送られてきていない。お金だけ支払って本体が消息不明になったという人まで出ている。

今回、自分もこの騒動に巻き込まれており、こちらの場合はまだ支払いを完了できていない。MSのサポートに支払いを終わらせるように何度もお願いしているのに、自分の英語力が足りないせいなのか、未だに精算を完了してもらえていない。このままだとオーソリの有効期限が来て、無料でSurface Book 2を手に入れてしまうことになりそうだ。

なお、今回も転送には 1worldshopping を利用した。何度も高額の品物を依頼しているが、今のところ事故ったことはない。サポートも、日本時間に日本語の窓口へメールすれば、きちんと日本語で返ってくる。DHLの配送ログは以下のようになった。最終的には佐川急便が11/25の夕方に、届けてくれている。

Saturday, November 25, 2017 Location    Time    Piece
18  Delivered - Signed for by : DLVD BY AGNT    KAWASAKI    14:54
17  Forwarded for delivery  YOKOHAMA - JAPAN    08:09

Friday, November 24, 2017   Location    Time    Piece
16  Forwarded for delivery  YOKOHAMA - JAPAN    14:04   
15  Arrived at Delivery Facility in YOKOHAMA - JAPAN    YOKOHAMA - JAPAN    12:37
14  Departed Facility in TOKYO - JAPAN  TOKYO - JAPAN   11:57
13  Processed at TOKYO - JAPAN  TOKYO - JAPAN   11:55
12  Clearance processing complete at TOKYO - JAPAN  TOKYO - JAPAN   11:22
11  Arrived at Sort Facility TOKYO - JAPAN  TOKYO - JAPAN   11:03
10  Customs status updated  TOKYO - JAPAN   09:26   
9   Transferred through NARITA - JAPAN  NARITA - JAPAN  09:25

Thursday, November 23, 2017 Location    Time    Piece
8   Departed Facility in CINCINNATI HUB - USA   CINCINNATI HUB, OH - USA    04:54
7   Processed at CINCINNATI HUB - USA   CINCINNATI HUB, OH - USA    03:48

Wednesday, November 22, 2017    Location    Time    Piece
6   Processed at CINCINNATI HUB - USA   CINCINNATI HUB, OH - USA    10:56
5   Shipment on hold    CINCINNATI HUB, OH - USA    06:37
4   Arrived at Sort Facility CINCINNATI HUB - USA   CINCINNATI HUB, OH - USA    01:25

Tuesday, November 21, 2017  Location    Time    Piece
3   Departed Facility in WEST PHILADELPHIA - USA    WEST PHILADELPHIA, PA - USA 22:26
2   Processed at WEST PHILADELPHIA - USA    WEST PHILADELPHIA, PA - USA 22:23
1   Shipment picked up  WEST PHILADELPHIA, PA - USA 15:14

  1. 最初に買ったSurface Pro 3は国内で買った。

今日は「Club MySQL #2:(MySQLの)XProtocolはじめました、Haskellで」の日です

マニアックなイベント に来てますので、メモを残しています。

XProtocol始めました、Haskellで / Naoto Ogawaさん

  • 意外とHaskellの人が多いかな、と
  • haskellMySQLで半分半分
  • XProtocol
    • ProtocolBuffer
    • Xはクロス (いろいろな言語から)
    • CRUDスタイルAPIもある
    • ドキュメントストアとの親和性
    • パイプライン処理(これに注目したい)
  • XDev API
    • EBNFの定義がある
    • BNFとは? → 文法を定義したもの
    • 複数DBサーバのコネクション管理も含む(理解しきれてないけど)
  • XPluginをMySQLへインストールする
    • Xdev API経由でユーザプログラムが利用
  • world_x データベースをサンプルとしてインストールしておくと良い
    • doc_id があるテーブルがドキュメントストアとして扱われる
    • _iddoc 内のJSONのものとも一致させる
    • _idGENERATED だけど自動に作ってくれるわけではない。アプリが入れる
  • mysqlx.so を入れる
  • mysqlsh
    • 3306 ではなく 33060 を使う(スライドではミスって 33061 だけど)
    • プロトコルを覗くプロクシを作ったためミスった
    • mysql-js> というプロトコルで、JSのコードを実行できる
    • find("$.GNP = 828")$ はルートのイメージ
    • *ワイルドカードが使えたり
  • XProtocolのドライバが文字列の式を解釈して、XProtocolにしてあげなければならない
    • 昔のドライバは、サーバ側でSQLをパースしている
  • XProtocolとして生のSQLを投げることは可能
    • .find とかを使って、一部だけをSQLにするとかはダメ
  • 様々な知識が必要だが、今日は「XProtocolの仕様」と「ProtocolBufferの理解」
    • 課題: 名前の衝突、TLSの難しさ、パーサライブラリの選択など → 作り直しかも
  • .proto ファイルにも仕様が書かれているので、読んだほうがいい
  • .proto ファイルから、ツールを使って各言語のオブジェクトを生成する
  • XProtocol
    • メッセージ長、タイプ、ペイロード(protobuf)、の繰り返し
    • 全体のメッセージ長がない
    • 全体のメッセージ長が欲しいのは、実装上のチョイス。ストリーミング処理すれば不要かも
    • メッセージ長はリトルエンディアン
    • 例えば ClientMessages のタイプ 19CRUD_UPDATE
    • EXPECT_OPENEXPECT_CLOSE はパイプライン処理用
    • ServerMessages で、 RESULTSET_FETCH_DONE_MORE_RESULTSETS が来たら、フェッチの残りがあるということ
  • Find メッセージ
    • collection スキーマやテーブル
    • criteria WHERE句
    • args バインド
    • grouping_criteria having句
    • 17 CRUD_FIND
  • protobuf は、フィールド名は送っていない。数字のタグのみ
    • protoファイルに定義されている

本当はこわいMySQLプロトコル / tmtmsさん

  • RubyMySQL X Protocol 作ってたけど、今日は古いプロトコルの話
  • 参照系: フィールド数でループ。レコードはEOFまで
  • クライアントはクエリが更新系か参照系かは知ってない
    • サーバから戻ってくるフィールド数を見て、判断する
  • LOAD DATA LOCAL INFILE
    • クエリをサーバが解釈。ファイル名をサーバに教えてもらう(!)
    • Proxyでサーバ名を書き換えることができる!
    • Proxyはクエリを LOAD DATA LOCAL INFILE に書き換えることができる(!!!)
  • 対策
    • SSL接続
    • クライアント側で LOCAL INFILE を無効化

XProtocol始めました、Haskellで(後半) / Naoto Ogawaさん

  • 結果セット Row メッセージ
  • Expr で表現
    • LITERAL Scalar V_SINT
  • ProtocolBufferのzigzag encoding
    • -99197 となる
  • 関数はドライバが文字列をパースして XProtocol の表現に
    • 構文解析の知識が必要
    • SQLで利用される関数すべてが、XDevAPIでサポートされているとは限らない
    • 関数名を XXX などとした場合は、サーバ側がエラーとする
    • SUM(DISTINCT hoge) とか 'a' not_regex 'aaa' とかできなかったり
  • パイプライン
  • エラー処理
    • Error メッセージとして却ってくる
    • protoファイル側に書いてある
  • XProtocolの注意
    • ObjectとErrorが2箇所くらいある
    • protoファイルごとに名前空間を変えてみては?
  • ドライバの設計
    • 型の整合性とか
    • 正常であればメッセージがあるケースとか
    • ドライバのレイヤの厚さは?
    • 依存を少なくしたいとか
  • haskellのライブラリ
    • XDev APIのEBNFには従ってない
    • XProtocolっが正しく吐ければいい
  • 展望
    • 交渉、ストリーミング、データ型、結果セット分割、などなど
  • MySQL5.7で試している
    • bindの謎の文字列は、文字列じゃなくていいでしょ
  • RubyでのXProtocolの実装を再開しようかな」
  • このプロトコルはGA?? わからず
  • プロトコルオタク的には楽しいけど、一般人の用途は・・・?

この会について

  • いつもは短い話を聞く会
  • 長くじっくり聞く会として、この会を開いている
  • また来てください

Haskell入門という本を書きました

Haskell入門 という本を書きました。まだ店頭で買うことはできませんが、amazonでは予約を開始しています。また、電子版も早いうちに出ると聞いているので、そちらもあわせてお求め下さい。技術評論社さんのサイトではサンプルのpdfも読むことができます。

Haskellには すごいH本 というとても良い教科書がすでにありますが、「アプリケーションを作って楽しむ」という観点から書かれた本も欲しいなということを常々感じていました1。すごいH本でHaskellの考え方やプログラムの組み方は学べますが、例えば、プロジェクトを作成して開発を始めるにはどうするかであったり、必要なライブラリをどこから探してどのように自分のプロジェクトへ組み込むのかといった、開発に必要な基本的な事項は自分で学ぶ必要があります。今回執筆した Haskell入門 ではとにかくHaskellでアプリケーションを作ることにフォーカスし、1冊読むだけで自分の作りたいアプリケーションが作れるようになることを目指して書かれた本です。

本書を書くにあたって、特に次のような点を意識しました。

  • ビルドツールの使い方や必須ライブラリの紹介、サンプルアプリケーションの作成といった内容を含む、よくあるプログラミングのhow-to本の構成にする
  • 新しいトピックを意欲的に取り込み、今現在の生きているHaskellを伝えられるようにする
  • 理論的な背景に踏み込み過ぎず、言語機能を使うユーザの立場で説明する
  • 複雑なGHC拡張の利用を最低限に留め、 Haskell 2010 Language Report の仕様の範囲内でできるだけ素朴にアプリケーションを作る

基礎を固めるためのチュートリアルはほどほどに、 とにかくまずは何か動くアプリケーションを作って、それを足がかりに学びたい という人に向いている本です。そういった意味では、先日発売された重城さんの Haskell 教養としての関数型プログラミング とは逆の思想を持って書かれた本であると言えます。

この本はもともと、YAPC::Asiaでレポーターとしてご一緒した技術評論社の野田さんに声をかけられて初めたものです。ただ、私はHaskellは昔から好きだったものの、自分一人では説得力のある本を書くのは難しいと考え、 ruiccさんちゅーんさん のお二方に声をかけました。Haskellに精通したお二方の協力により、なんとか完成までこぎつけることができました。

Haskellは学術のためだけの言語ではなく、品質の高い堅固なアプリケーションを作るために最適な言語です。ぜひ Haskell入門 を読んで、Haskellを使ったアプリケーションを作ってみて下さい。今でも最新の研究成果を貪欲に取り込み続けるHaskellに、きっと大きな刺激を受けることでしょう。


  1. 個人的には Real World Haskell が好きでした。