命令的 Haskell プログラミング

めいっぱい imperative に書いてやったぜ :p
やってることはそれほど自明ではないのに、main :: IO () って型には何の情報もないなぁ。IO () なんて自明な型に潰れやがって。。。

module Main where

import Control.Concurrent
import System.Environment

main :: IO ()
main = do
     { kbd1:scr1:kbd2:scr2:_ <- getArgs
     ; chan1 <- newChan 
     ; chan2 <- newChan 
     ; fini1 <- newEmptyMVar
     ; fini2 <- newEmptyMVar
     ; forkIO $ talk "Alice" (kbd1,scr1) (chan1,chan2) fini1
     ; forkIO $ talk "Bob"   (kbd2,scr2) (chan2,chan1) fini2
     ; takeMVar fini1
     ; takeMVar fini2
     }

talk 
  :: String                     -- 名前
  -> (FilePath, FilePath)       -- (キーボード入力,端末スクリーン)
  -> (Chan String, Chan String) -- (相手へのメッセージチャネル,相手からのメッセージチャネル)
  -> MVar ()                    -- スレッドの終了通知変数
  -> IO ()
talk name (kbd,scrn) (input,output) fini 
  = do
  { keyboardIn    <- readFile kbd
  ; let myTweets  =  map (add name) $ lines keyboardIn
  ; yourTweets    <- getChanContents  input
  ; timeLines     <- mergeIO myTweets yourTweets
  ; let shownTLs  =  unlines timeLines
  ; forkIO $ writeFile scrn shownTLs
  ; writeList2Chan output myTweets
  ; putMVar fini ()
  }
  where
    add bird inputLine = bird ++": "++ inputLine