Concurrent Clean : リストIO

[id:lethevert:20060905:p1]のコメント欄で思いついたモナドをリストに見て、順番に食わせれば・・・というネタを実装してみようと思ったのですが、
よく考えてみると、Haskellモナドは左結合ですね。リストは右結合なので、出来上がる構造が逆になってしまいます。
でも、あろはさんところで紹介されていた「Monads for Functional Programming (PDF)」を見ると、結合性は本質ではないそうなので、言語設計者の趣味の問題ですかね。しかし、現実のプログラミングでは、そういうところが結構気になったりするものなのですが。
さて、次のようなプログラムを作ってみました。今回はHaskellではなくCleanで。

module ListIO

import StdEnv

::Void = Void
::IO a b :== a -> *File -> *(b, *File)
::ListIO a = EndIO
           | E.b: (>=>) infixr 0 (IO a b) (ListIO b)

set a _ f = (a,f)
writes a f # f = fwrites a f
           = (Void,f)
writei a f # f = fwritei a f
           = (Void,f)
readi _ f # (_,i,f) = freadi f
          = (i,f)

run =  set "Please input integer\n"
   >=> writes
   >=> readi
   >=> writei
   >=> set "\nend\n"
   >=> writes
   >=> EndIO

perform :: a (ListIO a) *File -> *File
perform _ EndIO f = f
perform a (p >=> lio) f
    # (b,f) = p a f
    = perform b lio f

Start w # (f,w) = stdio w
          f = perform Void run f
          (_,w) = fclose f w
        = w

>=>というデータ構築子を定義して、perform関数で頭から順に実行していくように実装してみました。
ところで、これで、存在型の使い方をまた1つ覚えました。