あどけない話

インターネットに関する技術的な話など

Haskellの講義に関するQ&A

岡山大学で、関数プログラミングの講義を一コマ担当しました。資料は、函数プログラミングの集いで使った関数プログラミングの道しるべを流用しました。ちゃんと用意しなくて、講義を受けた学生には申し訳ないです。

講義内容に関して質問を頂きました。同じような疑問を持つ人も多いと思いますので、担当教官の許可を得てここに公開します。

永続データプログラミングの意義は分かったが,破壊しないと効率が悪いのではないですか.配列のような構造が世の中には多い気がします.メモリは足りなくなりませんか.

基本的に永続と呼ばれているデータは、共有の効率が高く、しかも不要になった部分はすぐに GC に回収されます。また、GHCGC はすごく優秀であることが知られています。

Haskell では、下位のレイヤーではデータを破壊できて、たとえば固定長のバッファーを使い回すといったことも可能です。ただ、それは普通のプログラマーには見えないようになっています。

型推論とは何でしょうか.

型推論とは、あらかじめ知っている型を手がかりにして、明記されてない型を推測することです。推測した型が全体として矛盾していなければ、型に関する間違いがないことが証明されます。という訳で、関数型の型推論とは型検査を含む大きな概念です。

一方、現在型推論を持つと言われる命令型言語の型推論は、省略された自明な型が分かるだけで、型検査の補助的な機能でしかありません。(関数型の型推論に比肩する型推論を持つ命令型言語の存在を僕は知りません。)

このように、型推論にも意味が二つあるので気をつけて下さい。関数型のはすごくて、命令型のはしょぼいと理解しておけば十分です。

I/O の処理は難しいと聞きますが,どのような対策を取るのですか.HTTPライブラリなどありますか.

それは都市伝説です。Haskell では、副作用を持つコードと純粋なコードを明確に分けて書く必要があります。この分け方を習得できない人が「Haskellは入出力が難しい」と言うようです。printf デバッグのやり方を知らないだけなのに、できないと勘違いして、難しいと言っている人もいるようです。

GHC の作者である Simon Peyton Jones は、「Haskell はもっとも素晴らしい命令型言語だ」と言っていることから分かるように、入出力の処理は簡単です。インターリーブIO、ユーザスレッドなどのおかげで、僕には C で入出力を処理するプログラムを書くのよりも簡単に感じます。

HTTPライブラリは、複数あります。

Scala はオジェクト指向と関数型のハイブリッドだと聞きますが,両者の概念の共存は可能なのでしょうか.

参照透明性とか遅延評価にこだわらないなら可能です。それにこだわっているHaskellは、関数型言語の中でも特殊な存在です。

現在,Haskell を用いたもので有名なプログラムは何ですか.

GHC 自身でしょうね。最近では、Yesod がホットです。

MLの講義では,コンパイラの型検査で何度も弾かれたため,なかなか小さいプログラムでも書けなかった.関数型言語での大規模プログラムの例が知りたかった.

ML のコンパイラーに通らないということは、明らかにバグがあるということです。コンパイラーが厳しくない他の言語で書いたら、簡単にコンパイラーに通ると言っても、そのコードはバグだらけで、後のデバッグで苦労するはずです。

大規模なコードを作る場合は、他の言語と同じように分割統治します。すなわち、モジュールを作成したり、モジュールの集合であるパッケージ(ライブラリ)を作成したりします。

MLの講義では,型が厳しいのが面倒だと思っていたが,バグが出ないという意味で便利なものだということを改めて感じた.

型はあなたの友達です。あなたがその価値を認めれば、型も心を開いてくれます。Rubyの聖地でHaskellを語るという資料を読んでみるといいかもしれません。

Haskell は,かなりイケテルと思った.

そうでしょう。なるべく早い時期にイケてる言語に触れるべきですよ。

不格好なfor文と JavaScript の話が新鮮で面白かった

ありがとうございます。Douglas Crockford さんのエッセイは面白いので、一度読んでみるといいでしょう。

できれば,演習を交えながら,3,4コマ使って受けたかった.

宮崎大学では演習もやりました。資料を公開しているので、興味があればやってみて下さい。

プログラミングは覚えることだらけで,今一好きになれないのですが,何かコツのようなものはありますか.

プログラミングとは、自分のやりたいことを表現する手段です。そもそも、表現したいことがないのではないですか? 表現したいことがあるなら、文法なんかを覚えることは苦にならないですよ。

力の弱いものから使うという発想はなるほどと思った

言われないと気付かないですよね。

現在の知識では,理解が難しかった.

すいません。

永続データプログラミングは,書換えが必要になる度に新しくデータを作るので,メモリが足りなくならないのでしょうか.Cでも再帰をするとスタックが溢れるんですが.

C には末尾再帰の最適化の機能がありませんが(最適化するコンパイラーもあるようですが)、多くの関数型言語では最適化されるので、単なる goto と一緒になり、スタックは溢れません。

授業でMLを習ったが,はっきりとは言われなかったので,関数型プログラミングの意義について疑問があったが,山本先生の講義でよく分かった.オジェクト指向について学んだ直後だったので,双方の比較もためになった.また,ところどころに面白い話が入っていて,Haskell に対してとてもいい印象を持った.講義時間が足りなかったのが残念.

どうもです。

木の更新がなぜ,g を継ぎ足さないで,d,fをコピーするのかよく分からなかった.

継ぎ足すということは、子供を持たされるノードを書き換えることを意味するからです。ポインターの指す場所も変更してはいけません。

Haskell を聞いたことなかった.そんなに流行っているのですか.勉強した方がいいのでしょうか.

流行っているかと言われれば、一部のプログラマーでしか流行っていません。あなたが、将来プログラマーになりたいと思っているなら、Haskell から得るものはとても多いでしょう。僕は、Haskell を学んで、はじめてプログラミングとは何か分かりました。それまでも分かっているつもりでしたが、気のせいでした。

xs = ['a'], ys = ['b', 'c', 'd', 'e'] の2つの配列を結合して zs = xs:ys において,配列が新たに作られるのは,メモリ効率が悪いのではないですか.

配列のことを言っているのか、リストのことを言っているのか定かではありませんが、リストの連結は効率は悪いです。しかし、命令型で配列を連結するのだって効率は悪いです。

型検査が通った後に発生するバグとはどんなものですか.

値に関するバグです。たとえば、0 で割ってしまうとか。