Haskellをまたちょっと書いてブチ切れ

昨日のことなんだが...
Haskellは難しすぎる.いや違うな,難しいんじゃなくて使い辛い.所詮は型理論の実証実験で,実用的なソフトウェアをそれで書いて経済活動するようなものではないと思った.サーバ・サイドならまだしも,パッケージで配るクライアント・アプリでは特にね.
まず数時間悩んだのは

  1. cmd.exe を立ち上げる
  2. その cmd.exe に vcvars32.bat を call させる
  3. その cmd.exe に echo %PATH% を実行させることで,2.で設定された %PATH% の値を読み取る
  4. 読み取った値を ; で分割してディレクトリの列を得る
  5. 列の中で cl.exe を含む最初のディレクトリを返す

というプログラム.System.Directory.doesFileExist がIOアクションなのでめんどい.まぁ確かに,まさにIOのアクションなんだけど,ディレクトリ構造を読むってフィーリング的には純関数的なlookupなんだよね... あと大抵の関数型言語って map を使えって口うるさいけど,ループを途中で抜ける系とは本質的に相性悪いんだよな(本来の言葉の意味に立ち返れば,それって "map" じゃないし).Monadと遅延評価でイディオムがあったように思うが,foldとMaybeで誤魔化してしまった.
とりあえず %PATH% の値が手に入ってから後はこんな感じで一応実現できた:

import Control.Monad as CM
import System.Directory as SD
import System.FilePath as SF

findExe :: String -> String -> IO (Maybe String)
findExe exeName pathEnvVarVal =
  CM.foldM
    (\mb -> \dir ->
       case mb of
         Just _ -> return mb
         Nothing ->
           do exist <- SD.doesFileExist $ dir `SF.combine` exeName
              if exist
                then return $ Just dir
                else return Nothing
    )
    Nothing (SF.splitSearchPath pathEnvVarVal)

(注意: ブラウザ上で手編集してるのでコンパイル通らないかも)
とりあえずIOアクションの do では,C互換の for, while, do-while を用意してくれないかな... 全てモナドで統一的に! とか気張らなくていいからさ.
cmd.exe とのやりとりは popen(2) 的な System.Cmd.runInteractiveProcess で可能.

  • id:sirocco:20090527:1243393335 Haskell から Ruby を呼ぶ - sirocco の書いてもすぐに忘れるメモ

System.IO.hGetContents って何? という話なんだが.リファレンスを読んでもいまいちピンと来ない.POSIXの言葉で説明してくれないと分からないよ...
100行以上のプログラムをHaskellで書こうとなるとインデントルールがウザすぎる... *1 Pythonは改行位置を強制的に定めているからまだインデントしやすいんだよな.do 大先生を始めとして if-then-else とか case-of とか,みんなどうしてるんだ? とにかく,自由形式の言語が最高だよ.Lispとかね.

さて現在,実行ファイルのフルパスをどう取得すればよいかで悩んでいる.Cで言う argv[0] はググったら方法が見つかったんだけど.

Cレベルでは以下のように(可搬性はないが)多くのプラットフォームで解が見いだされている.

FFI! FFI!

追記: popen はCランタイムの関数だった... (syscall すなわち (2) でなく (3) ) 死にたい...

*1:See also id:camlspotter:20100521:1274446264