読者です 読者をやめる 読者になる 読者になる

by shigemk2

当面は技術的なことしか書かない

第2期 第13回 H本読書会 in 秋葉原 #readhbon

勉強会 Haskell

readhbon.doorkeeper.jp

Random 擬似乱数について

  • コンピュータで真の乱数を発生させるのは困難で、数の偏りが発生する
  • 偏りなく、予想が困難で、素早く生成させる乱数を作るのは困難

擬似コード(ifが重い、6ばっかり出てくるなど)

while(true) {
  if (x == 6) {
    x = 1;
  } else {
    x += 1;
  }
}

なので、コンピュータでは擬似乱数を使う

周期のとても大きな関数

f(f(f(f(種))))....

擬似乱数の周期を決めておく

  • 種。擬似乱数のシードとはスタート位置を決めるための値
  • スタート位置が同じなら、それ以降の計算の値はすべて同じになる
  • スタート位置を決めるためにはプログラムの外から副作用を取り込む
  • Haskellの場合、IO(モナド)が必要になる

  • 乱数の初期化の値がバレるとシステムにとっては弱点で、種がバレると乱数の値がバレる

前回のおさらい

第8章は標準入出力で、第9章はファイルを扱う

9. もっと入力、もっと出力

9.1 ファイルとストリーム

  • 入力のリダイレクト コマンド入力を受け付けてファイルに出力する
  • 入力ストリームから文字列を得る 入力文字を全部大文字にする
  • 入力を変換する 入力を読み込んで回文かどうか解析する

9.2 ファイルの読み書き

  • ファイルをオープンする hGetContentsとかopenFileとか
  • withFile関数 openFileと一緒だけど関数を取って自動的にクローズ処理をやってくれる
  • ブラケットの時間 bracketを使ってwithFileを実装。メイン処理とクローズ処理を関数として受け取って、自動的に処理をやってくれる関数。
  • ハンドルを握れ! hGetContentsのhはhandleの意。このhがない関数もある。appendFileとかを使うと、ファイルを閉じる処理を自動的にやってくれるけど、試してみたけどクローズ処理が行われない場合もあるので注意されたし。

9.3 ToDoリスト

9.4 コマンドライン引数

  • ToDoリストを作る

gist.github.com

ここから。

9.5 ToDoリストをもっと楽しむ

  • タスクの閲覧
  • タスクの追加
  • タスクの削除
  • ファイル名を決め打ちにしない。

gist.github.com

不正な入力に対応

最後の引数がない場合に落とすように対応。なお、これだけじゃなくて引数がまったくないとか、そういうのにも対応しないといけないけどこのコードではできていない。

gist.github.com

9.6 ランダム性

参照透明性は、関数が同じ引数で 2 回呼ばれたなら必ず同じ結果を生成しなければならないことを意味する。遅延評価は参照透過の海の上で成立しているから。だが乱数は参照透過ではない。

  • System.Randomモジュールを使って乱数を表現する。
  • mkStdGenとrandomを組み合わせたいときは型注釈をしないといけない。
  • randomは「乱数ジェネレータ(ランダム性の源)を受け取り、ランダムな値と新しい乱数ジェネレータを返す
  • mkStdGenは乱数ジェネレータを作る。
random (mkStdGen 100) :: (Int, StdGen)

コイントス

gist.github.com

ランダムな関数をもっと

take 5とかしないと無限ジェネレータが出来るrandoms

randoms randomR randomRs

Prelude System.Random> take 5 $ randoms (mkStdGen 11) :: [Int]
[5258698905265467991,-1046130112415077602,3603401487739301952,-595625523242114439,-242088768969841391]
Prelude System.Random> take 5 $ randoms (mkStdGen 11) :: [Bool]
[True,True,True,True,False]
Prelude System.Random> take 5 $ randoms (mkStdGen 11) :: [Float]
[0.23626214,0.48899883,0.4896804,0.29281616,2.5201797e-2]
Prelude System.Random> randomR (1,6) (mkStdGen 10)
(6,440154 40692)
Prelude System.Random> randomR (1,6) (mkStdGen 1099)
(6,44015400 40692)
Prelude System.Random> randomR (1,6) (mkStdGen 1099)
(6,44015400 40692)
Prelude System.Random> take 10 $ randomRs ('a','z') (mkStdGen 2)
"ntgypxxjna"
Prelude System.Random> take 10 $ randomRs ('a','z') (mkStdGen 2)
"ntgypxxjna"
Prelude System.Random> take 10 $ randomRs ('a','z') (mkStdGen 20)
"ngyqbdordu"

ランダム性と I/O

ただし、getStdGenを2回実行しても同じ結果しか得られないので gist.github.com

こういうふうに改良する。 gist.github.com

再帰との組み合わせ

gist.github.com

(ちょっと手続き型っぽい書き方)

gist.github.com

9.6まで、次は9.7から。。

おまけ

qiita.com

1年間で20増える謎仕様

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!