Cogito Ergo Sum.

我思う故に我あり

リスト内包表記 2

 先日、Haskellのリストを処理する関数で、2つのリストの直積(direct product)を返す関数を探していて、僕は見つけられなかった。仕方ないのでリスト内包表記で書いた。

[(x, y) | x <- [0,1], y <- ['a','b']]

--[(0,'a'),(0,'b'),(1,'a'),(1,'b')]

 先日、見知らぬ人のブログを見ていて、我が目を疑った。全く同じ結果を返す以下のようなコード例が記されていたのだ。

main = print f
f = do
    x <- [0,1]
    y <- ['a','b']
    return ((x, y))

--[(0,'a'),(0,'b'),(1,'a'),(1,'b')]

 この「do記法」で書かれた一連の処理を1行で書いたものが、「リスト内包表記」なんだろうか…?

 これまでは、

[n * n | n <- ns]

のようなリスト内包表記の中で用いられる「<-」という記号と

line <- getLine

のような入出力で用いられる「<-」という記号は、同じ記号が異なる意味で用いられているのだろうと思っていた。そうではないってことなのか…。

 驚くと同時に、腑に落ちる感覚もあった。「リスト内包表記」に妙に「命令型(手続き型)言語」の匂いを感じていた僕だが、「do記法」は「リスト内包表記」なんて比較にならないホド「命令型(手続き型)言語」の匂いを放っている(と言うか、そもそも「命令型(手続き型)言語」風のコードを記述可能にするための記法が「do記法」なんだろうけど)。

 「リスト内包表記」も「do記法」もどちらも、Haskellというプログラミング言語にとってもっと本質的な機能(「モナド」とかその辺りの何か)のシンタックスシュガーに過ぎない、ということなのかな〜。

 この辺りの話は、Haskell入門を最後まで読めば、中盤過ぎ辺りで述べられているのだろうけど、僕は前半で躓いてしまっているので…。Haskellというプログラミング言語の学習には、Haskellの仕組みそのものの理解を楽しむ、という面もある。先を急がず、お楽しみは後にとっておこう(笑)。