119: List comprehension における Fail がランタイムエラーになる

↑up

概要

Prelude.hs を書いているなかで発見した件。 List comprehension においてパターンマッチが fail したときに、ランタイムエラーとなってしまう。

例えば、次のようなプログラム:

xs = [Just 3, Just 2, Nothing, Just 9, Nothing, Nothing, Just 8]
main = print $ sum $ [y | Just x <- xs, let y = x * 2]

これをコンパイル、実行しようとするとランタイムエラーとなる。

$ bunny testrun listcomprihension.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/listcomprihension --xno-implicit-prelude /home/unno/bunny/0.9.0/lib/Prelude.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/listcomprihension --xlibrary-path /home/unno/bunny/0.9.0/lib listcomprihension.hs
Error: Non-exhaustive patterns.

調査ログ

2020-12-13 (Sun)

そういえば、こころあたりがあった。 The Haskell 2010 language report の 3.11 List Comprehensions では、[e | p <- l, Q] の翻訳は次のように書かれている:

[e | p <- l, Q] = let ok p = [e | Q]
                             ok _ = []
                         in concatMap ok l

だが、私は当時、ok p が常にマッチするようにみえてしまい(p に任意のパターンが来うるので fail する可能性があるのだが、p が普通の引数に見えて勘違いした)、 以下のように実装してしまっていたのだった。

[e | p <- l, Q] = let ok p = [e | Q]
                         in concatMap ok l

というわけで、理由は簡単だった。仕様通りに直して解決。

概要のところに挙げたプログラムを test/sample323.hs とする。