Hatena::Grouphaskell

猫とC#について書く代わりにHaskellとF#について書くmatarilloの日記 このページをアンテナに追加 RSSフィード

2011-05-01

第3章 型とクラス #2

23:03 | 第3章 型とクラス #2 - 猫とC#について書く代わりにHaskellとF#について書くmatarilloの日記 のブックマークコメント

だんだんそれっぽくなってきた。

多相型

型の中に型変数を含めることで、任意の型に適用可能な関数を定義できる。これジェネリクスってことかなあ。

教科書に書いてあるlength関数の例は、

length :: [a] -> Int

なんだけど、C#で言えば、

static int Length<T>(IEnumerable<T> arg);

ってことのようだ。(C#では関数じゃなくてメソッドにするのが普通なので、そのように書いた。)

型変数には小文字を使うそうだ。

多重定義

新しい言葉が出てきた。クラスインスタンスHaskellでいうクラスはもちろんオブジェクト指向言語のクラスとは違う。クラスインスタンスは型なのだ。複数の型に共通する何かがクラスということらしい。

その後のところを読むと、どうもJavaC#でいうところのインターフェースが、Haskellクラスにちょっと似ている気がする。(でもきっと間違っているのだろう。間違いに気づくのはいつだろうか。)

クラスの話は後回しにして、多重定義型。最初の例が加算演算子+だったので、オーバーロードみたいなこと?と思ったがよく読むと違う。どうも、多層型がジェネリクスだとすれば、多重定義型は型制約のあるジェネリクスのように思える。

Haskellの例は

(+) :: Num a => a -> a -> a

となっているから、C#だと

static T Add<T>(T x, T y) where T : ICalculatable // ICalculatableインターフェースは今適当にでっち上げた

みたいな。(でもきっと間違っているのだろう。間違いに気づくのはいつだろうか。)

そして、数値も多重定義型っていうのはちょっと驚いたけど納得。だからIntコンテキストでもFloatコンテキストでも3というリテラル(?)を使えるのだ。C#の場合は数値リテラルの型が決まっていて、暗黙の型変換またはキャストができるという発想。違うもんだね。

基本クラス

上に書いたように、インターフェースだと思うと何となく納得。

Eqクラス
IEquatable<T>
Ordクラス
IComparable<T>
Showクラス
IFormattable。いやちょっと違うか。C#の場合はobject型にToString()メソッドがあるし。
Readクラス
IConvertible。これもちょっと違うけど。
Numクラス
C#にはこれに当たる型はない。組み込みの数値型には最初から演算子が定義されている。
Integralクラス
C#にはこれに当たる型はない。組み込みの数値型には最初から演算子が定義されている。
Fractionalクラス
C#にはこれに当たる型はない。組み込みの数値型には最初から演算子が定義されている。

div(/)の使い分けに注意かな。

練習問題

練習問題1
  • ['a', 'b', 'c'] :: [Char]
  • ('a', 'b', 'c') :: (Char, Char, Char)
  • [(False, 'o'), (True, '1')] :: [(Bool, Char)]
  • ([False, True], ['0', '1']) :: ([Bool], [Char])
  • [tail, init, reverse] :: [ [a] ]かな?init関数は教科書に出てきてないぞ。
    • Hugsで見てみた。おっと、関数だったのは分かってたはずなのに書きそこねた。[tail, init, reverse] :: [ [a] -> [a] ]だね。
練習問題2
  • second xs = head (tail xs) :: [a] -> a
  • swap(x, y) = (y, x) :: (a, b) -> (b, a)
  • pair x y = (x, y) :: a -> b -> (a, b)
  • double x = x * 2 :: Num a => a -> a
  • palindrome xs = reverse xs == xs :: Eq a => [a] -> Bool
    • リストはそもそもEqクラスなのかな?と思ってよく読み返してみたら、要素がEqクラスならリストもEqクラスということのようだ。
  • twice f x = f (f x) :: (a -> a) -> a -> a
    • これ少し難しいな。
練習問題3

Hugsで見てみた。演習問題1の最後の以外は合ってた!

それにしても、Haskell型推論はすごいな。

練習問題4

一般的に関数の型をEqクラスインスタンスにするのが実現不可能な理由?それって停止問題みたいなことかなあ。わからんからまた明日考える。