エラーハンドリング勉強会で発表してきました

発表資料はココで : http://ranha.kerox.info/start_exception.pdf

全体構成は3部です。
しかし、そのうち1つは、Exceptional C++とか(何か聞く所に依るともっと適切な本があるらしいですが)読むと例外安全とか例外中立を一々気にする姿勢について分かるし良いのではないでしょうか、ということの紹介みたいなものなので、実質2つです。

Haskellのパートは,StackのPushを何も気にせず代数的データ構造で表現すると

data Stack a = Empty | Push a (Stack a)

となって、このPushの型が

-- Push :: a -> Stack a -> Stack a

Stack aというEmptyであるかもしれない型を返すのが良くない。
更に、PopってPushの逆操作だからーということで

pop :: Stack a -> (a , Stack a)

みたいな型にすると、実装はEmptyの場合に例外を投げるか、返値の型をMaybe (Stack a)として失敗を表す値とするしか。
でもそうすると残りの部分全体にMaybeというか、計算の失敗が入って来て邪魔くさくなる。

いや、そもそも、なんでこんな不適切な型(Stack a)をPushが返す必要があるのか、GADTsを用いてEmptyではないStackを返すことをちゃんと書いてあげましょうみたいな話でした。

Cのパートは,簡単に言えばまぁヒープが死にましたみたいな、mallocがNULLを返すケース、これは何とか扱えそう。

あと、MaybeをCで実装するの面倒臭いですし、生みだされたものがマトモに使えるのか分からないので、別のアプローチの紹介をしました。

そもそもMaybeを使うのは、「関数の返す値で場合分け」をしたいからで、値を返さなければMaybeとか使う必要ないわけです。
ということで、失敗するかもしれない関数には「そこまでの計算が成功した場合の続き」と「そこまでの計算で失敗した場合の続き」を準備して(いわゆる継続です)あげればさしあたり上手くいきそうですよねーという。

ただ例外安全みたいなものを達成したい場合、シグナルが飛んでくる時(特に今回の場合は一段面倒臭いスタックオーバーフロー)にどう後片付けをして死ぬべきなのかという問題提起をしました。

ヒープアロケーションの成功失敗を気にするなら、まぁアラユル関数呼び出しでスタックが溢れる可能性があるわけでさてどうするべきなのでしょうか…。

更にCでなくC++の話をするとシグナル飛んで来て元に戻してあげないとデストラクタ呼び出されないわけで、更にどうするんでしょうかという感じです。

どうすれば良いのでしょうか…。