Haskellのerror関数が型破りなんだが型破ってない。
Thu Jun 13 22:52:36 JST 2013 (modified: Fri Sep 29 21:38:45 JST 2017)
views: 2696, keywords:プログラミング,Haskell,Haskell中毒 この記事は最終更新日が7年以上前のものです。
Haskellでコマンドを書いていて、エラーの出し方がよく分からないのでゴマカシゴマカシしていたのですが、真面目にオライリーの本を読んでるとerrorという関数を見つけました。ちゃんと例外処理をやるにはモナド使えとかなんとか書いてありましたが、コマンドならこれが一番いいかと。
例えば、標準入力から文字列を読んで最初の単語だけ出力するプログラムを書きます。
:~ ueda$ cat hoge.hs
uedamacimport System.IO
main :: IO ()
= getContents >>= putStrLn . firstWord
main
firstWord :: String -> String
= head $ words cs firstWord cs
こいつをコンパイルして実行すると実行できる訳ですが、単語を入力しないという意地悪をするとエラーが発生します。
:~ ueda$ ghc hoge.hs
uedamac1 of 1] Compiling Main ( hoge.hs, hoge.o )
[Linking hoge ...
:~ ueda$ echo This is a pen. | ./hoge
uedamacThis
:~ ueda$ echo | ./hoge
uedamac: Prelude.head: empty list
hoge:~ ueda$ echo $?
uedamac1
そんな意地悪な入力にはちゃんと教育的指導を与えなければいけません。error関数を使うとちゃんと自分でエラーメッセージを作文できます。
:~ ueda$ cat hoge2.hs
uedamacimport System.IO
main :: IO ()
= getContents >>= putStrLn . firstWord
main
firstWord :: String -> String
= if (length $ words cs) == 0
firstWord cs then error "no words"
else head $ words cs
はい実行。
:~ ueda$ ghc hoge2.hs
uedamac1 of 1] Compiling Main ( hoge2.hs, hoge2.o )
[Linking hoge2 ...
:~ ueda$ echo This is a pen. | ./hoge2
uedamacThis
:~ ueda$ echo | ./hoge2
uedamac: no words
hoge2:~ ueda$ echo $?
uedamac1
終了ステータスは1で固定なんでしょうか?まあ、今の時点ではよいでしょう。
んで、このerror関数を使うなとかなんだとかいろいろ議論はあるんですが、面白いのは型で、こんな定義になってます。
error :: [Char] -> a
出力が任意の型(a)になってるので、型のチェックに通るワケですね・・・。しかし、ずるいことにa型を返すと言いつつこいつは何も返しません。この関数が呼ばれると、他の処理を全部破棄して何も恐れるものの無い状態にしてからエラーを吐くだけなので、処理上、特に問題ないようです。
これ考えた人、これ考えたときどんな顔してたんでしょうね?
いろいろ興味が尽きませんが、寝るです。