週に一回は書きますよ 月に4つ記事を書けばノルマは満たされます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コードを try や catch の引数にしておけば、その外には例外は漏れない。そう思っていた時期が(ry

以下てきとうに。ソースは見てません。でもここら辺の挙動は別にghcのソース見なくても言語レベルで決まっている気がします。どこを読めばいいのかわかりませんが。

Haskellのlazy evaluationって、ようするにHaskellの型Aはすべてocamlにおける"() -> A"に対応する、とか考えておけばいいかしらと思っています。たとえば次のコード。

result <- try $ do
                let x = f 10
                return x
ここで帰ってくるのはxではなくて、評価するとxが帰ってくるサンクです。適当な関数f 10 はreturn xの時点ではまだ評価されていません。 tryから帰ってきた後でサンクを評価して例外が発生しても、tryでは捕まえてくれません。

これはどうにかならないんでしょうか。tryは外に返すサンクにも責任を持つとか。無理そうですが。

次善策として、返値をtryの中で積極評価してしまえば大丈夫です。上の例だと、次のようにseq xを導入すればokです。

result <- try $ do
                let x = f 10
                seq x $ return x
seq :: a -> b -> bは、 第一引数を必ず評価してから第二引数を返してくれます。積極評価のための関数です。こうしておけばxは評価され、tryの外では例外は起こりません。

ここまでがnyaasanのところでのコメントの補足です。


積極評価は、xがIntやFloatなど単純な値だとよいのですが、複雑な値、たとえばリストとかタプルとかだとまた厄介です。

result <- try $ do
        let x = (f 10, f 20)
        seq x $ return x
この場合、f 10やf 20が例外をはいたとしても、それはtryではつかまりません。seq xしていてもです。

x::(Int, Int)の場合、xを積極評価しても、xの中身は評価されません。具体的にMLのように書くと、評価する前のxの型は() -> (()->Int, ()->Int)のようなもので、seq xしても現れるのは(()->Int, ()->Int)です。xがなんかタプル二つであるというところまでしか評価されません。次のように中身を丁寧に評価すれば大丈夫です。

result <- try $ do
        let x = (f 10, f 20)
        fst x `seq` snd x `seq` return x
スポンサーサイト
コメント
この記事へのコメント
コメントを投稿する
URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
http://gusmachine.blog49.fc2.com/tb.php/273-2b4b1910
この記事にトラックバックする(FC2ブログユーザー)
この記事へのトラックバック
以前のHaskellの例外の記事を書いたときから考えていたことなのですが、ある値の要素をすべて正則評価する関数は書けるのでしょうか。値がた...
2008/02/02(土) 20:27:42 | 揺動散逸日記
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。