world"</hask>という文字列、あるいは<hask>map</hask>という関数と同様に値として扱われます。変数名に束縛したり、関数に引数として与えたり、関数の結果とすることが可能ということです。Haskellが扱う他の値と同様に、アクションにも型があります。アクションと呼ばれる非常に重要なアクションから始めましょう。このアクションはプログラムの外部に対して働きかけることができるアクションです。以上をみてわかるように、IOアクションは非常に単純なこと(文字列を出力する)から非常に複雑なこと(テレビゲーム)まで多岐にわたります。IOアクションはHaskellプログラムで使われる値として結果を残すことも可能であるということに気付いたと思います。コンソールから入力行を読み取る処理でポイントとなるのは、プログラムにデータを渡す部分です。アクション型は値型のように結果として提示するもの(たとえばString)と同様にアクションの種類(IO)も反映します。いう型を持っています。いう型を追っています。表記されます)が使われます。Javaといったプログラミング言語を知っている人はユニット型が"void"型の返り値と似たものだと思って下さい。アクションがプログラムに使われる値を結果として返す一方で、引数には一切とりません。引数をとりますが、アクションではありません。いうアクションの型を返す関数です。"hello"</hask>はアクションです。微妙な違いでしかないですが、重要なことです。IOアクションではそれ以上の引数を絶対にとりませんが、アクションを作る関数(たとえば<hask>putStrLn</hask>)は引数をとります。アクションというのは説明書のようなものです。アクションによって何ができるかを示しています。ことによって何かが起きます。アクションがあるだけでは何も起きないのです。"hello"</hask>は"hello"という行を表示するアクションです。()</hask>を持っています。次のような定義をもつHaskellプログラムを書いてみます。これではプログラムに"hello"と表示させることはできないのです!Haskellは"main"と呼ばれるIOアクションしか実行できないことになっています。()</hask>という型を持っています。「じゃあ1つのIOアクションしか実効できないなら、どうやってHaskellプログラムで実用的な事をさせられるんだろう」と疑問に思うかもしれません。前のほうで述べたように、IOアクションというのは非常に複雑です。たくさんの簡単なアクションをつなげて、複雑なアクションを作ることができます。doブロックは2つ以上のアクションを1つのアクションとしてつなげるものです。2つのIOアクションが結合されてその返り値がIOアクションだった場合、実行されるとまず最初のアクションが処理されて、その後に2番目のアクションが実行されます。簡単な例を見てみましょう。表示するアクションです。最初のアクションが副作用を持っていても、2つ目のアクション実行時にはその副作用を観測できる状態にあります。最初のアクションでファイルに書き込みが行われて、2番目のアクションで読み込みが行われたとき、ファイルの変更点は読み込みに反映されます。IOアクションはプログラムに結果を返すことができると言ったのを思い出してください。doブロックの結果はdoブロックの最後のアクションの結果となります。()</hask>となります。doブロックはあるアクションの結果を他のアクションの生成のために使うこともできます。String</hask>)というアクションを使っています。このアクションはコンソールから入力行を読み取ります。line)</hask>というアクションを先ほどの結果を<hask>line</hask>に束縛した形で呼び出します。ここで等号ではなく、矢印(<hask><-</hask>)が束縛に用いられていることに注意してください。矢印はアクションの結果がいままさに束縛されています、ということを表しています。String</hask>です。矢印はアクションの結果を<hask>line</hask>に束縛します。その型は<hask>String</hask>になります。これまでdoブロックを2つのアクションを繋げるために使ってきました。最下層のdoブロックはアクションなので、<hask>getLine</hask>と他のアクションを一緒に繋げることができます。lines"</hask>と繋げることができ、より複雑なアクションを作ることができます。幸いなことに、こんな面倒な書き方をする必要はありません。doブロックでは複数のアクションを1つのブロックに書き下すことができます。マルチアクション・ブロックの意味は前述の入れ子の例をみれば明らかだと思います。束縛はそれ以降の全てのアクションから観測可能です。先の例はこのようにコンパクトに書き直すことができます。プログラムを書くときは他の書き方をしても一向に構いません。全てのアクションは<hask>main</hask>に書く代わりに、共通の操作を、別のアクションとしたり、アクションを生成する関数としたりして切り出したくなることもあるでしょう。ここでは<hask>promptLine</hask>という関数を作りました。この関数はアクションを返します。()</hask>を使っています。これは文字列を改行せずに表示します)、コンソールから入力を読み込みます。このアクションの結果は最後のアクションの結果、つまり<hask>getLine</hask>となります。2行読みこんで、それらを結合して返すような便利な関数を書いてみましょう。これまでで、2行の入力行を読み込んでそれを結合する方法はわかっていますが、どうやって結合された文字列を返したらいいのか分かりません。doブロックはアクションをつなげて、その結果は最後のアクションの結果となることを思い出してください。line2</hask>は文字列でありアクションではないので、doブロックの最後に使うことはできません。いまここで必要なのは、ある特定の値を結果とするアクションを作る方法です。これこそまさに<hask>return</hask>関数が行う内容です。returnはどのような型の値も引数にとって、そのような値を結果とするアクションを作る関数です。String</hask>であり、その型自身は外部世界に影響を与えることはないですが、これで<hask>line1</hask>と<hask>line2</hask>を結合した文字列を結果とすることができました。ここで、多くの初心者が混乱してしまう、非常に重要な点を押さえておきましょう。returnはdoブロックの実行を"中断しません"。returnはよくdoブロックの途中で使われますが、それが必ずしもそのdoブロックの結果に関係があるというわけでもありません。returnというのは単なる関数で、特定の値を結果とするアクションを生成するというだけのことです。言い換えれば、値をアクションに"ラップしている"ということです。if-then-elseやcase-ofあるいはアクションの再帰のようなHaskellの制御フローを使うこともできます。<hask>if</hask>が真偽値によって2つの値から1つを選ぶような制御だということを思い出してください。want?"というアクションの結果にもとづいて2つのアクションから洗濯するような制御として使いました。この<hask>if</hask>の結果はdoブロックがより大きなアクションへと取り込みます。複数のアクションを<hask>then</hask>節や<hask>else</hask>節で実行したいと思ったら、さらに別のdoブロックを使ってそれらを1つのアクションにまとめなければいけません。let束縛もdoブロック内で用いることができます。doブロックを使っているときは、<hask>let</hask>を使うにあたってより便利な構文があります。<hask>in</hask>キーワードや入れ子を使わなくて良いというのがそれなのですが、この構文を使うときは、束縛された変数のスコープはdoブロック内の残りのアクションとなります。これは矢印を用いたdoブロック内でのdo束縛のスコープと同様です。let束縛とdo束縛はdoブロック内で自由に使うことができます。最後に一つ、ぜひ知っておくべきIOアクションの詳細について紹介します。それはアクションには逃げ道がない!ということです。IOアクションから結果を得たければ、(<hask>main</hask>を通じて)IOアクションを呼び起こして、その結果を他のIOアクションを通じて外部に影響を与えるしか方法はないのです。IOアクションから結果だけを取り出して値を得ること(逆<hask>return</hask>)はできないのです。IOアクションの結果が"ラップされていない状態で"存在できるのはdoブロックの中だけなのです。言い切ってはしまいましたが、ここで告白することがあります。あとで気づくことになりますが、実はこれは一部間違いがあります。非常にまれな状況で、IOから脱出することができるのですが、その方法を使わない方が良い理由が多いのでここでは上のように結論づけました。IOアクションはプログラムの外の世界に影響を与えるために使われる。アクションは引数はとらないが、結果の値は持つ。アクションは実行されるまで不活性なまま。Haskellプログラムの中ではたった1つのIOアクション(<hask>main</hask>)だけが実行される。doブロックは複数のアクションを1つのアクションにまとめる。まとめられたIOアクションは副作用が観測できる形で順番に実行される。矢印はdoブロック内でアクションの結果を束縛するために使われる。returnはアクションを作る関数である。制御フローの形式では"ない”。HaskellWikiDisclaimers。