OSTRACISM CO.

ScalaとHaskellとPythonと...

IOモナド

 IOモナドに汚染される感覚。実用的なプログラムには必ずI/Oがある。必ずある。にもかかわらず純粋関数型言語であるHaskellにおいてI/Oはモナドとして表現されている。モナドが絡むと面倒が一気に増えるように感じる。実際増える。ディレクトリ一覧を操作したいだけなのにIOモナドが付いてまわる。乱数を使いたいだけなのにIOモナドが付いてくる。現在日時を知りたいだけなのにIOモナドがひっ付いてくる。IOモナドを扱う関数を呼ぶ側にも必ずIOモナドを扱わせないといけない。コマンドラインパラメタにはIOモナドが付いてくるのでプログラムのmain側には必ずIOモナドがあるが、そこから呼ばれる関数にはIOモナドがある必要はない。しかし例えば乱数を使うとなるとその関数を含めそこからmainまでの全ての階層の関数にIOモナドを付けなくてはならない。これがIOモナドに汚染される感覚となる。IOモナドを封じ込める方法はあるようなのだが邪道とされている。困ったもんだ。モナドの何が面倒かって、mapでなくmapMを使わなくてはいけなくなる。ロジック的には普通にmapで表現できるはずのことがmapMでないと表現できなくなる。これって関数型言語一般の問題じゃないですよね。純粋関数型言語だからこその問題ですよね。しかもIOモナドは遅延評価をさせないためのHaskell特有の機能。簡単な問題を面倒臭く解く典型。

 shuffule_H.hsのshuffleMp3関数はIOモナドが付いている。ディレクトリをたどってファイルリストを得るのに加え乱数も扱っているためだ。ファイルリストを得るlistupFilesでは再帰の時にmapMを使っている。ロジック的にはmapで十分な部分なのだがIOモナドのおかげでmapMになってしまっている。普通にmapで書くべき部分でmapMなんて取って付けたような変な関数を使うのは実用性という点で正しいのかどうか疑問が残る。IOモナドという考えの妥当性に疑問がある。IOにモナドを導入して得たものは参照透過性。参照透過性や正格性がどれだけ大切かわからないが、私にはHaskellでは数千行が限度で、数万行は書けない、仕事には使えそうにないと感じた。IOモナドに汚染される感覚のせいである。

 ちなみにPythonもインタプリタのままでは数万行は書けないと感じる。ScalaはJavaやC/C++/C#と同じように数万行は普通に書ける。不純な言語(^^;)なのでモナドが漏れだすこともない。

 そうそうHaskellには変数や代入はないと書いたが、モナドではその二つのようなことが書ける。epub2to3_H.hs の関数 main の冒頭、

main = do
  args <- getArgs

 このargsは再代入はできないけどScalaのvalに相当する変数で、getArgsの結果を代入していると見做せる。見做せると書いたのは、きっと所詮シンタックスシュガーだからなんだが、そう見せるためのシンタックスシュガーなんだから素直にそう扱って良いかと思う。なんというかひどいツンデレですね。汚れ仕事は全部モナドに丸投げ。


2014.07.16

2014.08.28


「インデックス」へ戻る


OSTRACISM CO.

OSTRA / Takeshi Yoneki