LYH 8.1 入出力

8.1 入出力

8.1 不純なものと純粋なものを分離する

Haskellでは関数が副作用を持つことが許されない。木のようなデータ構造でさえ、要素を追加しようと思ったら、新しい要素をが追加された木を、新たに変数に束縛することで対応できた。しかし、入出力に関しては、どうやっても状態の書き換えが必須となる。ディスプレイの状態が書き換わらずにどうやってユーザが扱うことが出来るだろうか。また、一行の入力を求める関数があったとき、ユーザの入力は毎回異なるから、関数が生成する文字列は毎回異なる。どう対処すればよいか。

副作用が含まれる処理が、副作用を含まない処理に影響を与えなければ良い。副作用が含まれる処理の中で完結していれば、副作用を含む処理と含まない処理を分離して扱うことができる。

以下の一文を考えよう。

name <- getLine

前提知識がない状態だと、「一行を読み取って、変数に読み取った文字列を代入している」と読めそうである。

もしそうであれば、getLineの型は、getLine :: String だろうか。実際に:tで確かめてみると以下のように表示される。

getLine :: IO String

ここで、IO String は、Stringを生成するI/Oアクションと読むことが出来る。

生成されるStringは毎回同じではないため、getLineに副作用が存在している。しかし、I/Oアクションによって生成されたStringをnameに束縛していると考えると、Stringをnameに束縛する作業は副作用がない処理と変わりはない。I/Oアクションによって生成されたStringを置いておく箱から、Stringを取り出してくる処理として<-を用いることで、副作用のある処理と副作用のない処理を分離して考えることが出来る。

8.1 確認問題

  1. I/Oアクションとは何か。
  2. I/Oアクションがどうやって入出力を可能にするのか。
  3. 純粋関数型言語によって得られる利点を3つあげよ。

解答

  1. 実行されると副作用(入力を読んだり画面やファイルに何かを書き出したり)を含む動作をして結果を返すような何か。
  2. (WIP)
  3. 遅延評価、堅牢性、関数合成