25日目の記事として書かれました。定義したりすることができます。代替の紹介をしようと思います。定義域(domain)の要素に対して、値域(range)の値が高々1つ対応付けられるような対応付けのことです。対しては定義されません。Haskellでは部分関数を定義するのに、幾つかの方法があります。(コードがuncurry化されていることには特に意味はありません)。用いることも出来ます。1つはパターンマッチを網羅しないものです。Main.test対応するパターンが無い旨がエラーとして表示されます。部分関数での未定義をエラーとして補足することが非常に困難だからです。部分関数を排除するスタイルのコーディングをルールにしているものもあります2。困難なのか?部分関数の未定義を捕捉するのが困難なのには幾つかの理由があります。Haskellでは型の部分に現れません。型システムのチェックを利用できないということです。Haskellでの未定義の扱いHaskellでの未定義は実際には例外によって実現されています。例外を投げることができます。詳しく述べませんが、少なくとも幾つかの難しい部分があります。1つ目は、例外を拾うことができるのはIOモナドの中だけだということ。2つ目は、pureなコンテクスト下では、例外の発生も遅延されるということ。簡単な例を見てみましょう。標準入力から1行入力してスペース区切りの整数のリストを読み込みます。整数として正しくない文字列が入力された場合、例外が発生します。呼び出し、受け取った数の合計を表示します。getNumsが例外を発生させた場合は、空リストを受け取ったことにします。不正な入力が来た場合、表示されるものは0になるはずです。parse1つ目の実行結果は正しく動いているようです。望ましくない挙動です。これはまさしく例外の発生が遅延されているからです。別の場所で例外を起こしてしまうのです。例外をpureに投げることのできるHaskellでは知るすべはありません。例外を起こさせるようにする方法があります。numsしかし、残念ながらこれもうまくは動きません。弱頭部正規形)までしか評価しない、つまりリストの中身までは評価しないからです。データ構造をWHNFまでしか簡約できないからです。正規形)までの簡約を行うインターフェースを提供しています。これを利用することによって、先程の例は正しく動作するようになります。クラスのインスタンスにできるとも限りません。その最たるものが関数です。parseのように、非常に質素なものです。この例外が生成された場所を知る術がありません。今のところ簡単な解決方法はありません。大きなプログラムで突然何の情報もなくエラーで落ちる。どこが原因か全くわからない。デバッグは非常に困難です。近い将来GHCに実装されるのではないかと思われます。身近なところにも実はとてもたくさんあります。minimumEnumクラスのメソッド全般readなどなど、非常によく使うものが含まれています。部分関数ではありません。部分関数ではありません。これはIOのエラーとして例外が投げられます。そのための幾つかのオプションがあります。既存の部分関数を使うのを避ける先ほど挙げたPreludeの関数、及び他の標準的な部分関数を使うのを避けましょう。ドキュメントに頼ることになるでしょう。逆の、部分関数ではない関数を見分ける方法ならいくつかあります。よってエラーが通知される可能性が高いです返り値がMaybeあるいはEitherであるあえて部分関数にしている可能性は非常に低いです。それによってエラーが通知される可能性が非常に高いです。ようなものがあります。いったものを用いるのも良い代替でしょう。IOモナド版が用意されているものもあります。返り値にIOが付いただけですが、これが非常に重要なことです。先の例はとてもシンプルに書きなおすことができます。それを用いるのは有力な選択肢となります。作るのも避けなければなりません。パターンマッチ漏れを防ぐことは重要です。それらを無視せずにきちんと修正しましょう。考慮すべきオプションでしょう。部分関数を構築するプリミティブです。これらを使わないようにしましょう。置き換えれば問題は解決です。純粋な計算ではIOが混入することは嫌われるかもしれません。その場合にはMaybeやEitherを使うのが良いでしょう。ポリモーフィックにエラー通知をするのがスマートです。遅延IOの除去さて最後にもう一つ、厄介なものを紹介します。部分関数ではないものの、部分関数と同様に扱いにくいもの、遅延IOです。getContentsは標準入力からの遅延入力を行う関数です。入力は必要とされるまで実際には行われません。その入力を処理していたpureなコンテクストで例外が発生します。部分関数と同様にこれは非常に捕捉しにくいものになります。同様の現象が発生します。なる記事も書かれており、エラーハンドリングの困難さはその問題の1つとして挙げられています。堅牢なコードを書くためにこれを避けるのはもったいないものです。そちらをご参照ください。設計を見なおして使いやすくした代替ライブラリなどが出現しています。書き捨てのプログラム等では無理に除去する必要はないでしょう。代替手段を用意しておくべきです。それから正しくエラーを処理する必要があります。そのために、monad-controlというパッケージが非常に有用なのですが、それは又の機会に。あなたのHaskellプログラムが正しく動き続けますように。Bootswatch.。