人気ブログランキング | 話題のタグを見る

System.Random (17) Random クラス

System.Random 解読シリーズ

Random 型クラスは、乱数ジェネレータを利用して、様々な型のデータを発生させるときのクラスメソッドを提供している。クラスメソッドは Int 型でも Double 型でも同様の動作を行うときに共通の名前を使うことができ、操作の抽象化ができる。クラスメソッドはこのように多相型関数だが、実装は instance 宣言の時にそれぞれの型に応じて行う必要がある。

以下に、System.Random.hs のソースファイルの Random 型クラスの class 宣言のコメントを日本語訳したものを示す。

Random クラスは、乱数ジェネレータを利用して、プログラマに様々なデータ型の乱数を発生する手段を提供する。

最小限実装を定義すべき Random クラスの関数は randomR と random だ。

class Random a where

randomR は乱数の範囲 (lo, hi) と乱数ジェネレータ g を引数に取り、範囲 [lo, hi] の間の均一に分布する乱数および新しい乱数ジェネレータを値として返す。lo > hi の時の動作については特に明示していない。連続なデータ型については、lo と hi の値についての規定はないが、それらは、実装と範囲の値による。

  randomR :: RandomGen g => (a,a) -> g -> (a,g)

random は randomR と同じように乱数を発生するが、乱数のデータ型のデフォールトの範囲を使う。

Bounded タイプ(例えば Char 型のような有界のデータで Bounded クラスのインスタンス)では範囲はそのデータ型の全体になる)

分数型のデータでは、範囲は一般に [0,1) のような半閉区間になる。

整数型のデータでは、範囲は Int 型の範囲だ。

  random  :: RandomGen g => g -> (a, g)

randomR の変種。randomR と同じように指定した範囲の乱数を発生させるが、単一の乱数ではなく、乱数の無限リストを生成する。新しいジェネレータは返さない。

  randomRs :: RandomGen g => (a,a) -> g -> [a]
  randomRs ival g = x : randomRs ival g' where (x,g') = randomR ival g

random の変種。random と同じようにデフォールトの範囲の乱数を発生させるが、単一の乱数ではなく、乱数の無限リストを生成する。新しいジェネレータは返さない。

  randoms  :: RandomGen g => g -> [a]
  randoms  g      = (\(x,g') -> x : randoms g') (random g)

randomR の変種でグローバルの乱数ジェネレータを利用する。"System.Random#globalrng" を参照。

  randomRIO :: (a,a) -> IO a
  randomRIO range  = getStdRandom (randomR range)

random の変種で、グローバルの乱数ジェネレータを利用する。"System.Random#globalrng"を参照。

  randomIO  :: IO a
  randomIO   = getStdRandom random

このように、コメントを除くと class 宣言による型クラスのプログラムは、単に多相型関数の型の宣言をしているもの (randomR, rondom) と、その型クラスの多相型関数を利用して関数を定義しているもの(rondomRs, romdoms) の2種類がある。

型クラスについては、Haskell の学習を始めた頃は説明を読んでものことかよくわからなかった。それは Int 型や String 型などの低レベルのデータ型からボトムアップ式に理解しようとしていたからだ。

しかしながら、トップダウンで型クラスを眺めるとその意味が良く分かる。初めに抽象的な関数を型クラスのクラスメソッドとして定義しておけは、パターンが同じでデータ型が違うような処理に対して、同じ意味の処理に対しては同じ関数で対応できる。

実際のプログラムでもいきなり個々のデータ型についてのプログラムを始めるよりは、最初に型クラスとそのクラスメソッドを定義しておいて、あとで実装を考えるという方向性のほうが全体的な見通しが良くなるだろう。

今回の解読では型クラスの便利さに目覚めることができた。
by tnomura9 | 2015-05-07 18:35 | Haskell | Comments(0)
<< パターン認識読書法 自然数の集合とラッセルのパラドックス >>