GoAzure 2015 参加、そしてASP.NET 5 v1.0.0-beta2
金曜にhttp://r.jazug.jp/event/goazure/に参加してきました。
MSの中でOSSを推進しているScott Hanselmanが来日してセッションを持つということで、いろいろ聞いてきました。
そういえば以前、Scott Hanselmanのとある熱いブログ記事を日本語に訳してました。
それはともかく。
いろいろ話を聞いてる間に ASP.NET 5のbeta2が出てたので、matarillo.comのASP.NET記事を更新しておきました。
今のところの記事リストは http://matarillo.com/aspnet/ にあります。
LinuxでASP.NET vNextを動かしたい…がまだ成功してない(追記)動いた
(2015-01-01追記)matarillo.com: 1 ASP.NET 5をLinuxにインストールする (手動) をご覧ください。libuvのインストールはもっとシンプルになりました。
(追記)MacOS Xのひとはこちらをご覧になるといいと思います。
(追記)何はともあれ最初はMono 3.4.1以降を入れること。ディストロのデフォルトパッケージで配布しているMonoはバージョンが古い可能性があるので(たとえばUbuntu14のMonoは3.2.8だ)、Xamarinのパッケージか、コミュニティパッケージを探すといい。
https://github.com/aspnet/home に書いてあるとおりに進めようとしているのだが、KVM*1を入れた後、kpm restore
でこけた。
Warning: FindPackagesById: Kestrel Error: SendFailure (Error writing headers) GET https://www.nuget.org/api/v2/FindPackagesById()?Id='Kestrel'. (他にもいろいろ)
ぐぐってたらStackOverflowの回答が見つかった。理由はnuget経由でアセンブリをダウンロードする際に証明書がないから、とのこと。
$ sudo mozroots --import --machine --sync $ sudo certmgr -ssl -m https://go.microsoft.com $ sudo certmgr -ssl -m https://nugetgallery.blob.core.windows.net $ sudo certmgr -ssl -m https://nuget.org
で通るようになった。
続いて k kestrel
を実行したら
$ k kestrel System.DllNotFoundException: libdl at (wrapper managed-to-native) Microsoft.AspNet.Server.Kestrel.Networking.PlatformApis/LinuxApis:dlopen (string,int) (以下略)
でこけた。
libdlはglibcの一部らしいが、それが見つからないというのはLinux Mint 17 Qiana Xfce (64-bit) 固有の状況かもしれない。
$ ldconfig -p | grep libdl libdl.so.2 (libc6,x86-64, OS ABI: Linux 2.6.24) => /lib/x86_64-linux-gnu/libdl.so.2 libdl.so.2 (libc6, OS ABI: Linux 2.6.24) => /lib/i386-linux-gnu/libdl.so.2
うーむ。まだ解決してない。
(追記)
https://github.com/aspnet/Home/issues/172 を見て、Monoのデバッグ出力を設定。
$ export MONO_LOG_LEVEL=debug $ export MONO_LOG_MASK="dll" $ k kestrel
するといろいろ出力された。
(省略) Mono: DllImport attempting to load: 'api-ms-win-core-file-l1-2-0.dll'. Mono: DllImport error loading library '/home/kinomata1/.kre/packages/KRE-Mono.1.0.0-beta1/bin/libapi-ms-win-core-file-l1-2-0.dll': '/home/kinomata1/.kre/packages/KRE-Mono.1.0.0-beta1/bin/libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. (省略) Mono: DllImport error loading library 'libapi-ms-win-core-file-l1-2-0.dll': 'libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport unable to load library 'libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport attempting to load: '__Internal'. Mono: DllImport loaded library '(null)'. Mono: DllImport searching in: '__Internal' ('(null)'). Mono: Searching for 'ReadFile'. Mono: DllImport attempting to load: 'api-ms-win-core-file-l1-2-0.dll'. Mono: DllImport error loading library '/home/kinomata1/.kre/packages/KRE-Mono.1.0.0-beta1/bin/libapi-ms-win-core-file-l1-2-0.dll': '/home/kinomata1/.kre/packages/KRE-Mono.1.0.0-beta1/bin/libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. (省略) Mono: DllImport error loading library 'libapi-ms-win-core-file-l1-2-0.dll': 'libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport unable to load library 'libapi-ms-win-core-file-l1-2-0.dll: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport searching in: '__Internal' ('(null)'). Mono: Searching for 'ReadFile'. Mono: DllImport attempting to load: 'libc.so.6'. Mono: DllImport error loading library '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libc.so.6': '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libc.so.6: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport error loading library '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libc.so.6.so': '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libc.so.6.so: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport loaded library 'libc.so.6'. Mono: DllImport searching in: 'libc.so.6' ('libc.so.6'). Mono: Searching for 'uname'. Mono: Probing 'uname'. Mono: Found as 'uname'. Mono: DllImport attempting to load: 'libdl'. Mono: DllImport error loading library '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libdl': '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libdl: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport error loading library '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libdl.so': '/home/kinomata1/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-beta1/lib/aspnet50/libdl.so: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport error loading library 'libdl': 'libdl: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport error loading library 'libdl.so': 'libdl.so: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport error loading library 'libdl': 'libdl: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport unable to load library 'libdl: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. Mono: DllImport attempting to load: 'libdl'. (省略) Mono: DllImport unable to load library 'libdl: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません'. System.DllNotFoundException: libdl (省略)
ふむ、/lib
の方を見に行ってないようだ。ldconfig
では見つかるのに。LD_LIBRARY_PATH
が必要なのか?と思って試しにexportしてみたが、やはりlibdlでこけた。うむー。
いやまて、上のデバッグ出力をよく見てみると、libcの方はKestrelの下を2回見に行ったあとで成功しているが、libdlは同じタイミングで「共有オブジェクトファイルを開けません」になってるな。/lib
を見に行ってるけどうまく拾えていないとか?
(追記)issue 172にlibtoolとlibuvを入れたら通ったって言うのが出てるな。あとでやってみる。
(追記)issue 172のコメントを見て、libtoolを入れ、libuvのv1.0.0-rc2をビルドしてインストールし、libuv.dylibからlibuv.soにシンボリックリンクを貼ってみたが、やはりだめ。
$ k kestrel System.NullReferenceException: Object reference not set to an instance of an object at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.loop_size () [0x00000] in <filename unknown>:0 at Microsoft.AspNet.Server.Kestrel.Networking.UvLoopHandle.Init (Microsoft.AspNet.Server.Kestrel.Networking.Libuv uv) [0x00000] in <filename unknown>:0 at Microsoft.AspNet.Server.Kestrel.KestrelThread.ThreadStart (System.Object parameter) [0x00000] in <filename unknown>:0
コメントにあるように、Kestrelは1.0.0-alpha4じゃないとだめなのだろうか。違いはそこぐらいしかないのだが(自分の環境は1.0.0-beta1だ)。
(追記)1.0.0-alpha4にしてみた。
$ cd ~/aspnet/Home $ git checkout v1.0.0-alpha4 $ cd samples/HelloWeb $ kpm restore
ってやって、
$ cd ~/.kpm/packages/Microsoft.AspNet.Server.Kestrel/1.0.0-alpha4/native/darwin/universal/ $ mv libuv.dylib libuv.dylib.org $ ln -sf /usr/local/lib/libuv.so libuv.dylib
ってシンボリックリンクを貼って、
$ cd ~/aspnet/Home/samples/HelloWeb $ k kestrel
(しかし、Ctrl-Cではkestrelを停止できずに、最後にはkill -9した→追記:libuvの1.0.0正式版だったら大丈夫になった)
(12/26追記)libuv.dylibからlibuv.soにシンボリックリンクを貼る以外の方法があるようだ。後で試して、記事自体を書きなおすか……→書いた。
パーサーコンビネーターって書きたくなるよね、C#的なまとめ
パーサーコンビネーターっていうのはオブジェクトをぺこぺこ結合することで望みのパーサーを合成できるっていう、そういったたぐいのもの。
- (U^ω^)わんわんお! - @linerlockの日記
- liner_lockさん作、Parseq
- 関数型言語ってこわい?C#erがLINQでパーサーに挑戦(1) - 猫とC#について書くmatarilloの雑記
- bindで毎回詰まる人の為のパーサーコンビネータの仕組み
- karino2さんの一連の解説。
- karino2さんの解説記事には、LINQで簡単DSLというのもあります。
- karino2さんが参考にされているSpracheは、Nugetでインストールできます。
「なんでLINQなんだ?」と疑問に思った方は、私のサイトのモナド解説記事でも呼んでいただければ幸い。
Re: Scala の implicit parameter は型クラスの一種とはどういうことなのか
Scala の implicit parameter は型クラスの一種とはどういうことなのか - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴くのブックマークコメントに
(続く記事も読みました)C#/Java的に言うと、型クラスは型制約なんですよね。とある型をとある型クラスのインスタンスに「後から」できるかどうかは本質ではないという理解。
と書いたらば、
型制約というだけならば trait でいいじゃないかという話になってしまい、わざわざ型クラスを導入するメリットがないので、やはり既存の型に対する拡張が可能というのは型クラスの本質(の一部)ではないかなぁという理解をわたしはしています。実際型クラスの存在しない C#/Java でも、サブタイピングでの型制約は実現できているわけですし、「なぜわざわざ型クラスを導入する必要があるのか」という視点から見ると、サブタイピングでは実現できない柔軟さを実現する必要があるからかな、と思います。「そうじゃないんだ」「それはこういう理由で本質的には型制約と同等なのだ」という意見があれば是非参考にしたいので教えてください。
という追記がついたので、すこし補足しておきます。
型クラスに対するわたしの理解は、Philip Wadler と Stephen Blottの論文 "How to make ad-hoc polymorphism less ad hoc(PDF)"をベースにした、「パラメトリック多相とアドホック多相の中間」です。
パラメトリック多相はC#/Javaでいうところのジェネリクスですね。一方、アドホック多相はC#/Javaではメソッドや演算子のオーバーロードがそれにあたります。この区分はML系言語でもたぶん同じと理解してます(間違ってたら誰かコメントください)。Haskellにはオーバーロードがなく、アドホック多相を実現するには型クラスを使うことになるのですが、型クラスをパラメトリック多相の側から見れば、英語版Wikipediaのように Bounded parametric polymorphism(境界のあるパラメトリック多相) ととらえることもできると理解しています。
で、C#/Javaにとっては、境界のあるパラメトリック多相に該当するのはジェネリクスの型制約しかないわけです。なので、「型クラスは型制約(の仲間)」と言いたかったのですが、ブコメにはカッコの中を書かなかったので、なんだかおかしな主張をしているような感じになってしまいました。HaskellやScalaの型クラスが、C#/Javaの型制約と全くイコールだ、と言いたいわけじゃないんです。
C#/Javaの型制約は、継承をベースにしているので、インスタンスメソッドは呼べますが、静的メソッドは呼べません。C#のジェネリクスで、演算子が使えなくてイライラした人も多いのではないでしょうか?(C#のジェネリクスが値型も対象にできるのはいいことなんですが、算術演算に悩んだりとか、ありますよね。)型クラスは型に対して関数が定まる仕組みですから、C#/Javaから見ればむしろ全てが静的メソッドですね。さらに、ある型クラスがほかの型クラスを拡張するという仕組みもあり、そういうのをC#/Javaでシミュレートしようとすると、インスタンスメソッド群を定義したオブジェクトを追加のパラメータとして渡す、いわゆる「貧者の型クラス」にするしかないわけです。そこを暗黙のパラメータを使って、明示的に渡さなくても推論させることができるのがScalaの型クラスです。
と、ここまでなら暗黙の変換はいらないわけですが、「既存の型に対する拡張」ができた方が自由度が高くて便利だし、実際Haskellの型クラスだってinstance
宣言を後付けできるわけです(こちらも間違ってたら誰かコメントください)。“Haskellの”型クラスと同じことをScalaでやるには、暗黙の変換を使うという風に理解していますが、それがもしできなかったとしても、継承をベースとした型制約にできないことが型クラスではできる、ということに違いはないのではないでしょうか。
(2016/9追記)けっこう前の記事に今更追記するのもあれなんですが、Olegさんの型クラス解説ページにわかりやすく書かれていますね。型クラス(の実装)は、型に対応づいた関数群であり、この関数群の1インスタンスを渡すことがDictionary Passing、辞書渡し。Haskellの場合はコンパイル時に暗黙的に関数群が渡されるけど、OCamlのように型クラスという機構がない言語ではプログラマーが自分で関数群を渡すしかない。このHaskellにおける「暗黙的に関数群が渡される」をScalaで実現するのがimplicit parameterということで、元記事はそのように述べていましたね。
私は「ワドラーらが論じた一般的な型クラスというものがあって、その一つの特殊例がHaskellの型クラスだ」と言わんばかりの論調でしたが、Haskellの型クラスがむしろ一般的な型クラスの在り方なのかもしれないと思いなおしました。今更ですが、すみませんでした。