|
|
||
こう書けるべき!
[d| 'name = 'rnd |]
まぁはすけるは(- 1)が函数にならない時点で終焉です。時代は受験です受験!!
まくぶくしばらくしまおうか……
それ Template Haskell でできるよ!
PerlとC++にしかできないような気がするアノ機能(挑戦者募集中) - 簡潔で覚えやすいタイトルを3秒で思いつく程度の能力
とはいいつつ若干(かなり)ルール無視なかんじで、まあとりあえず代入する変数(束縛する函数)をランダムで決めればいいよね……と解釈しました。
ルール厳守版だと、 id:eagletmt さんが TwitterでIORefで書いてるのがすでにありますし、なによりぼくはむかし IORefとunsafePerformIOくんには痛いメに遭っているのできらいです。eagletmtさんはunsafeつかってないけど、とにかくきらいです。
そこで、1/2の確率でaまたはbをランダムに定義するプログラムを書いてみました。ルールからは外れますが気にしてはいけません。
RandomDef.hs:
{-# LANGUAGE TemplateHaskell #-} module RandomDef where import Language.Haskell.TH import System.Random $( do rnd <- runIO $ randomIO let nm = mkName (["a", "b"] !! (rnd `mod` 2)) sequence [runQ $ valD (varP nm) (normalB [| rnd |]) []] )
Main.hs:
import RandomDef main = print a
Template Haskell の制約上、なんか二つに分けなきゃいけないのが不満ですが、こんなかんじです。
実行すると1/2の確率で勿論失敗します。
実行:
$ runhaskell Main.hs 515889430 $ runhaskell Main.hs 586851382 $ runhaskell Main.hs Main.hs:2:13: Not in scope: `a' $ runhaskell Main.hs 341328210 $ runhaskell Main.hs Main.hs:2:13: Not in scope: `a' $ runhaskell Main.hs 697186460 $ runhaskell Main.hs Main.hs:2:13: Not in scope: `a' $ runhaskell Main.hs 2076927286
けなげですね。すばらしい。シュレーディンガーのはすけるですね!意味がわかりません。
まあ、日頃おカタい静的なヤツだと思われてるはすけるちゃんも、実は意外と動的なところあるじゃん……みたいな認識が日本に広まれば、僕はきっと受験に合格すると思います。しなかったらはすけるちゃんの所為です。はすけるちゃん、立派な大人になってください。美味しゅうございました。
勉強をサボってHOC (Haskell Objective-C Binding) でTwitterクライアントを書いてみました。
一通りタイムラインの定期確認と発言は出来る様になってます。
あとIntelならGHCがインストールされてない普通の環境でも動くと思います。
PPCの人はお手数ですが自力でビルドしてください。
$ runhaskell Setup.hs configure $ runhaskell Setup.hs build
とでもやれば出来ると思います。人によっては --user が必要かも。
コンパイルする場合は HaXml と HTTP と HOCと utf8-stringがrequiredなのでいれといてください。バイナリになっちゃえば関係ないです。
感想としてはまあ、クラス弄るなりなんなりするところは、ここまで来るとObj-Cでやった方が早い。意味わかんないinstance宣言しないといけないし。
ただまあHaskellのスレッド機構を使えたり、XMLパースにHaXmlつかったりできるところはやはり強みだと思う。そうそう、今回はHaXmlお試しの意味も込めてました。簡単に書けすぎてお試しにならなかったかもしれませんが、とにかくHaXmlは簡単でした。
余談だけど HaXml と Haml は名前がややこしい。Hamlは亡びるべきですね!!
全体的に見ればなかなか快適な開発だったと思います。あとはIBが自動的にソース読んで、Outlet と Action を自動設定してくれるといいんですが、まあ希望です。
RubyCocoaの方がまあObj-Cとはパラダイム的にもマッチしているので、やっぱりあの快適さには敵いません。
その内Haskell Ruby Obj-C ハイブリッド(?)なアプリとか書くのもいいかもしれませんね。
HOCプログラミングの方法論はまあコード読んで貰えればわかると思いますが、そのうち詳しく書いてみようと思います。
動作画面は以下。
アイコンはHaskellリスペクトな感じでこんなんです。
(2009/09/07 一部編集・追記)
昨日から今朝に掛けて、@shelarcy さんに 助けられながら Data Parallel Haskell (dph; データ並行 Haskell) と格闘した続報&まとめ。
あと、後で書いた『Unlifted と vectoriseの簡単な比較』の方にvectorise と Unliftedの比較を手短に纏めたので、そちらも見てください。
『DPHまとめ』に同じ。
Unlifted最新版。
{-# LANGUAGE PArr, PackageImports #-} {-# OPTIONS_GHC -Odph #-} module Main where import qualified "dph-prim-par" Data.Array.Parallel.Unlifted as U import qualified "dph-prim-seq" Data.Array.Parallel.Unlifted.Sequential as S import System.Environment import Data.Char toDigits :: Int -> U.Array Int toDigits = U.fromList . map digitToInt . show forEachDigit fn = U.sum . U.map fn . toDigits forEachDigit' fn = U.map fn . toDigits f = forEachDigit (S.productU . S.enumFromToU 1) sf = forEachDigit id . f g i = sub 1 where sub n = if sf n == i then n else sub (n+1) sg = forEachDigit id . g sumsg x = S.sumU . S.mapU sg . S.enumFromToU x main = do args <- getArgs case args of (x:y:_) -> print $ sumsg (read x) (read y) (x:[]) -> print $ f $ read x _ -> putStrLn "use just as you like"
$ ghc -Odph -fdph-par -fdph-seq unl.hs --make -threaded $ time ./unl 1 30 291 ./unl 1 30 1.13s user 0.63s system 89% cpu 1.976 total $ time ./plain 1 30 291 ./plain 1 30 0.01s user 0.00s system 95% cpu 0.018 total
ここから先の最適化は各自でがんばりましょう。
HOC (Haskell Objective-C binding) が普通にインストール出来る様になったみたいです。
$ svn co http://hoc.googlecode.com/svn/trunk/hoc
$ cd hoc
したら、あとはREADME.txtに書いてある通りに、
$ cabal configure $ cabal build $ cabal install $ cd Bindings $ sh make-bindings-macos.sh $ cd ../Tools $ cabal configure $ cabal build $ cabal install
とすれば普通にインストール出来ちゃいました(環境に依っては--user とか sudo とか必要かもしれません)。
Samples/以下のサンプルも普通にビルド出来ました。やったね!
Data Parallel Haskell で格闘した結果歯医者に行くことになった経緯は前記事を参照のこと。
その後、歯医者から帰ってくると、Twitter で @shelarcy さんから アドヴァイスを頂いてました。
@mr_konn 残念ながら、現在の DPH の vectoriser はあまり賢くありません。http://bit.ly/11iJoE -dph-seq を代わりに使って逐次版を作らせてみると、"Stack space overflow"になってしまうのが分かると思います。
http://twitter.com/shelarcy/status/3777048271
との事で、そうかぁ現行安定版ではまだ発展途上なんだなぁ……と。
@mr_konn 念のため手元にある ghc-6.11.20090803 を使って試してみました。こちらではちゃんと結果を返してくれますね。-fdph-par を使うとかなり遅くなりますが、-fdph-seq ならリスト版と比べてもそれほど遜色のない速度で答えを返してくれます。
http://twitter.com/shelarcy/status/3777587520
と云うことなので、未来の発展に期待です。
その後、shelarcyさんが勧めてくださった aggressively optimized for insanity - Data Parallel Haskell fun を読む。どうやら Data.Array.Parallel はラッパみたようなもので、まだまだ未実装な部分が多く、プリミティヴな実装である Data.Array.Parallel.Unlifted 充分早く動く、と云う風に理解する。
Unlifted は果してvectoriseするのかなぁどうなのかなぁなんて頓珍漢なことを考えていたら、
@mr_konn 現在の所、[:a:] に対する操作を Unlifted な配列に対する操作に変換するのが vectorise (flattening) の役割なので、Unlifted に対する vectorise はそもそも不要です。(将来的にはそうでなくなるかもしれませんが)
http://twitter.com/shelarcy/status/3778602025
との事で、それじゃあunlifted使ってみるべ、と。
まずProblem 10 を軽く解いてみる。200万までの素数の総和を求める。ただし200万までやると時間かかるので、適当に10万まで。
リスト版(Plain10.hs):
module Main where primes = sieve [2..100000] sieve xs | null xs = [] | otherwise = let (p:ps) = xs in p:sieve [q | q <- ps, q `mod` p /= 0 ] sums = sum primes main = print sums
Unlifted 版 (Unl10.hs):
{-# LANGUAGE PArr #-} {-# OPTIONS_GHC -fdph-par #-} module Main where import qualified Data.Array.Parallel.Unlifted as U import Data.Array.Parallel.Unlifted.Parallel primes = sieve $ U.enumFromTo 2 100000 sieve xs | U.length xs == 0 = U.empty | otherwise = let p = U.replicate 1 (xs U.!: 0) ps = dropUP 1 xs in p U.+:+ (sieve $ filterUP (\q->q `mod` (p U.!:0) /= 0) ps) sums = U.sum primes main = print sums
コンパイル:
$ ghc --make Plain10.hs $ ghc -Odph -fdph-par Unl10.hs --make -threaded
計測結果:
$ time ./Plain10 454396537 ./Plain10 6.38s user 0.07s system 98% cpu 6.524 total $ time ./Par10 454396537 ./Unl10 2.69s user 0.02s system 99% cpu 2.733 total
Unlifted速い!異常に速い!
Parallel.Unlifted にも Parallel.Unlifted.Parallel にも product が無かった。ライブラリのソースを見ている内に、productUPを発見する。が、なぜかexportされていない。ので、書き写す。こんなんなった。
{-# LANGUAGE PArr #-} {-# OPTIONS_GHC -fdph-par #-} module Main where import qualified Data.Array.Parallel.Unlifted as U import System.Environment toDigits :: Int -> U.Array Int toDigits 0 = U.empty toDigits n = let (d, m) = (n `divMod` 10) hds = toDigits d in hds U.+:+ (U.replicate 1 m) productUP :: U.Array Int -> Int {-# INLINE productUP #-} productUP = U.fold (*) 1 forEachDigit f = U.sum . U.map f . toDigits f = forEachDigit (productUP . U.enumFromTo 1) sf = forEachDigit id . f g i = sub 1 where sub n = if sf n == i then n else sub (n+1) sg = forEachDigit id . g sumsg x = U.sum . U.map sg . U.enumFromTo x main = do args <- getArgs case args of (x:y:_) -> print $ sumsg (read x) (read y) (x:[]) -> print $ sg $ read x _ -> putStrLn "use just as you like"
こんぱいる&実行。
$ ghc -Odph -fdph-par Unl254.hs --make -threaded $ time ./Unl254 2 Unl254: thread blocked indefinitely ./Unl254 2 0.00s user 0.00s system 80% cpu 0.004 total
え・・・っ?
色々試行錯誤した結果、fが全ての元凶であることを突き止める。突き止めたが、どこがわるいのかわからない。多分、forEachDigit や productUP や U.enumFromTo を多重に組み合わせている所為っぽいんだけど、よくわからなかった。歯(があった場所)が痛い。
今日はここでタイムアップ。
Par254.hs(並列処理部分) :
{-# OPTIONS -fvectorise -fdph-par #-} {-# LANGUAGE PArr #-} module Par254 where import Data.Array.Parallel import Data.Array.Parallel.Prelude import Data.Array.Parallel.Prelude.Int import GHC.PArr (toP) import qualified Prelude toDigits :: Int -> [: Int :] toDigits n | n == 0 = emptyP | otherwise = let d = (n `div` 10) m = (n `mod` 10) hds = toDigits d in hds +:+ singletonP m forEachDigit f n = sumP ( mapP (f) ( toDigits n)) f = forEachDigit (¥a -> productP(enumFromToP 1 a)) sf n = forEachDigit (¥a->a) ( f n ) g i = sub 1 where sub n = if sf n == i then n else sub (n+1) sg n = forEachDigit (¥a->a) ( g n ) sumsg x y = sumP (mapP sg (enumFromToP x y))
254.hs (表示部分) :
module Main where import Par254 import System.Environment main = do xs <- getArgs case xs of (x:y:_) -> print $ sumsg (read x) (read y) (x:_) -> print $ sg $ read x _ -> putStrLn "usage: just you like"
コンパイル:
$ ghc -c -Odph -fdph-par Par254.hs $ ghc -Odph -fdph-par 254.hs --make -threaded
$ time ./254 20 15 ./254 20 0.10s user 0.11s system 121% cpu 0.174 total $ time ./254 1 20 (終わらない)
sumsg の定義から sumP を取り除くと早く終わるんだけど、このままだと sumsg 1 2 すら終わらない。何で?
あとCharが使えなかったり、 ポイントフリースタイルが使えなかったり、パターンマッチ出来なかったりdphは発展途上すぎると思いました。
なので、親知らずを抜いてくることにします。
そう云えばsumP抜いたときの結果をわすれてた。
Par254.hs :
sumsg x y = mapP sg (enumFromToP x y)
にsumsgの定義を置き換える。
実行
$ time ./254 1 20 [:1,2,5,6,7,3,4,5,6,7,8,8,9,13,9,10,11,13,14,15:] ./254 1 20 0.52s user 0.56s system 127% cpu 0.853 total
はやい!
$ time ./254plain 1 20 [1,2,5,6,7,3,4,5,6,7,8,8,9,13,9,10,11,13,14,15] ./254plain 1 20 0.00s user 0.00s system 91% cpu 0.007 total
もっとはやかった!
module Main where import System.Environment toDigits :: Int -> [Int ] toDigits 0 = [] toDigits n = let d = (n `div` 10) m = (n `mod` 10) hds = toDigits d in hds ++ [m] forEachDigit f = sum . map f . toDigits f = forEachDigit (product . enumFromTo 1) sf = forEachDigit id . f g i = sub 1 where sub n = if sf n == i then n else sub (n+1) sg = forEachDigit id . g sumsg x y = map sg $ enumFromTo x y main = do xs <- getArgs case xs of (x:y:_) -> print $ sumsg (read x) (read y) (x:_) -> print $ sg $ read x _ -> putStrLn "usage: just you like"
と云う訳で、歯医者いってきます
(追記:2009年09月現在、普通にインストール出来る様になったみたいです! HOCがインストール出来る様になったみたいです - はてな使ったら負けだと思っている deriving Haskell - haskell 参照。)
HOC と云う、HaskellからObjective-Cを叩くためのバインディングがあります。
これは主にghc-6.8.x系統を対象としてるみたいで、GHC-6.10.x系統には手直ししないとインストール出来ないみたいです。と云う訳で、勉強の合間に少しずつ四苦八苦しつつ結局行き詰まった記録。
共有ライブラリとかオブジェクトファイルとかの事をあんまり(と云うか殆んど)知らない状態でやろうと云うのが間違いなのかもしれませんが……こうしてみたら?と云うアドバイスがありましたら是非お願いします。
OSX 10.5.7 + MacBook (1.3GHz Intel Core 2 duo)
$ ghc -v
Glasgow Haskell Compiler, Version 6.10.4, for Haskell 98, stage 2 booted by GHC version 6.10.3.20090628
$ ghc-pkg list
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./package.conf:
Cabal-1.6.0.3, HUnit-1.2.0.3, QuickCheck-1.2.0.0, array-0.2.0.0,
base-3.0.3.1, base-4.1.0.0, bytestring-0.9.1.4, cinnamon-0.2,
containers-0.2.0.1, directory-1.0.0.3, (dph-base-0.3),
(dph-par-0.3), (dph-prim-interface-0.3), (dph-prim-par-0.3),
(dph-prim-seq-0.3), (dph-seq-0.3), extensible-exceptions-0.1.1.0,
filepath-1.1.0.2, (ghc-6.10.4), ghc-prim-0.1.0.0, haddock-2.4.2,
haskell-src-1.0.1.3, haskell98-1.0.1.0, hpc-0.5.0.3, html-1.0.1.2,
integer-0.1.0.1, mtl-1.1.0.2, network-2.2.1.2, old-locale-1.0.0.1,
old-time-1.0.0.2, packedstring-0.1.0.1, parallel-1.1.0.1,
parsec-2.1.0.1, pretty-1.0.1.0, process-1.0.1.1, random-1.0.0.1,
regex-base-0.72.0.2, regex-compat-0.71.0.1, regex-posix-0.72.0.3,
rts-1.0, stm-2.1.1.2, syb-0.1.0.1, template-haskell-2.3.0.1,
time-1.1.4, unix-2.3.2.0, xhtml-3000.2.0.1
/Users/*****/.ghc/i386-darwin-6.10.4/package.conf:
HaXml-1.13.3, binary-0.5.0.1, darcs-2.2.1, fgl-5.4.2.2,
haskeline-0.6.1.6, parsec-3.0.0, plugins-1.4.1, terminfo-0.2.2.1,
terminfo-0.3.0.2, utf8-string-0.3.5
$ cabal -V
cabal-install version 0.6.2
using version 1.6.0.3 of the Cabal library
$ svn co http://hoc.googlecode.com/svn/trunk/libffi $ cd libffi/src $ ../configure --prefix=/usr/local CFLAGS=-DMACOSX $ make $ sudo make install $ svn co http://hoc.googlecode.com/svn/trunk/hoc
BUILDING.CVS と云うファイルがあるが、しかし、つかわれているのはSVNだしなぁ……と思いつつ書かれている通りにやってみる。
$ ./autogen.sh + exec autoconf $ ./configure checking build system type... i386-apple-darwin9.7.0 checking host system type... i386-apple-darwin9.7.0 checking target system type... i386-apple-darwin9.7.0 = snip = config.status: creating HOC_cbits/Makefile config.status: creating InterfaceGenerator/Makefile config.status: creating InterfaceGenerator2/Makefile config.status: creating Tools/Makefile $ make for dir in HOC_cbits HOC InterfaceGenerator InterfaceGenerator2 Bindings Foundation AppKit Tools docs ; do (cd $dir; echo "In directory $dir"; make all) done In directory HOC_cbits = snip= [13 of 31] Compiling HOC.Exception ( HOC/Exception.hs, build/objects/HOC/Exception.o ) HOC/Exception.hs:73:23: Not in scope: `throwDyn' HOC/Exception.hs:82:8: Not in scope: `catchDyn' HOC/Exception.hs:88:26: Not in scope: `catchDyn' make[1]: *** [ghcmake.build-stamp] Error 1 = snip = ../inplace.conf: openBinaryFile: does not exist (No such file or directory) make[1]: *** [hocwrap] Error 1 In directory docs pod2html \ --index \ --header \ --title="HOC: a Haskell to Objective-C bridge" \ --outfile "HOC.html" \ Introduction.pod Quick_Start.pod Mapping_Types.pod Accessing_Other_Frameworks.pod Creating_an_Objective-C_Class_in_Haskell.pod Tools.pod Appendices.pod
どうやら例外処理の方法が古いみたいで Control.OldException にしないと駄目っぽいな……と当りをつけて、HOC/HOC/Exception.hs の import Control.Exception を import Control.OldException に変えて再挑戦。
$ make [27 of 31] Compiling HOC.Utilities ( HOC/Utilities.hs, build/objects/HOC/Utilities.o ) [28 of 31] Compiling HOC.StdArgumentTypes ( HOC/StdArgumentTypes.hs, build/objects/HOC/StdArgumentTypes.o ) Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Loading package unix-2.3.2.0 ... linking ... done. Loading object (static) ../HOC_cbits/HOC_cbits.o ... done Loading object (dynamic) objc ... done Loading object (dynamic) ffi ... done Loading object (framework) Foundation ... done ghc: unknown symbol `_setIvarInList' final link ... linking extra libraries/objects failed make[1]: *** [ghcmake.build-stamp] Error 1 = snip = ../inplace.conf: openBinaryFile: does not exist (No such file or directory) make[1]: *** [hocwrap] Error 1 In directory docs make[1]: Nothing to be done for `all'.
むう。だめだ。
そもそも.CVSなんて信用するから悪かったんだ!と逆ギレして、 しばらくオンラインをさまよう。
すると、何故か Yi の READMEに詳しく載っていたので、の云う通りにしてビルドしてみる。cabal-install で色々パッケージを管理しているので、 --prefix=/usr/local の代わりに --user をつける。
$ runhaskell Setup configure --user
Configuring HOC-1.0...
$ runhaskell Setup build
Compiling HOC_cbits...
= snip =
[11 of 31] Compiling HOC.Exception ( HOC/HOC/Exception.hs, dist/build/HOC/Exception.o )
HOC/HOC/Exception.hs:23:28:
Not in scope: type constructor or class `SomeException'
= snip =
HOC/HOC/Exception.hs:51:19:
Not in scope: data constructor `SomeException'
おっと。何か新しいExceptionに対応したみたい(?)なのでさっきの OldException を再びException に戻す。
$ runhaskell Setup build Compiling HOC_cbits... Preprocessing library HOC-1.0... Preprocessing executables for HOC-1.0... = snip = [30 of 31] Compiling HOC.CStruct ( HOC/HOC/CStruct.hs, dist/build/HOC/CStruct.o ) [31 of 31] Compiling HOC ( HOC/HOC.hs, dist/build/HOC.o ) Warning: the following files would be used as linker inputs, but linking is not being done: HOC_cbits.o ghc: no input files Usage: For basic information, try the `--help' option.
ここで止まってしまう。見るとdist/build/HOC_cbits.oは生成されている模様だが……。
ここで良くわからなくなったので、 本家のGoogle Code で似た様な報告が無いか見る。
あった。Issue 12。
どうやら、6.10.xのcabal君が HOC_cbits.o をCのソースファイルとして扱うとかなんとかで、兎に角上手くいかないらしい。
折角インストールした6.10.xを6.8.xに戻すのはイヤなので二つ目の方法を取る。つまり、
A slightly less quick workaround is to remove the 'c-sources' line in the .cabal file and manually link HOC_cbits.o into the build product (both the .a and the .o).
http://code.google.com/p/hoc/issues/detail?id=12
と云うことなので、 HOC.cabal から 67行目の
c-sources: HOC_cbits.o
を削除。再び、
$ runhaskell Setup configure --user Configuring HOC-1.0... $ runhaskell Setup build Compiling HOC_cbits... Preprocessing library HOC-1.0... Preprocessing executables for HOC-1.0... Building HOC-1.0... = snip = [26 of 27] Compiling Output ( InterfaceGenerator2/Output.hs, dist/build/hoc-ifgen/hoc-ifgen-tmp/Output.o ) [27 of 27] Compiling Main ( InterfaceGenerator2/Main.hs, dist/build/hoc-ifgen/hoc-ifgen-tmp/Main.o ) Linking dist/build/hoc-ifgen/hoc-ifgen ...
となって平穏無事に終わった。やった。
さて、HOC_cbitsをちゃんとつくる。下の方のComment 5 で出てたpatch を当てる。
The attached patch lets me build with base 4.0.0 (using Control.OldExceptions) with some hand-tweaking of
libHOC_cbits.dylib:
(略)
(will build HOC_cbits and HOC, then fail)
(略)
copy libHOC_cbits.dylib to ~/.cabal/lib (or elsewhere in my ghc-pkg config library path)
(make sure HOC_cbits is an extra library in ghc-pkg's HOC package descriptor)
http://code.google.com/p/hoc/issues/detail?id=12
手順通りやってみる。
$ ./configure OBJCFLAGS='-arch i686' CFLAGS='-arch i686' LDFLAGS='-arch i686' --with-dynamic-haskell CFLAGS='-fpic -dynamic' OBJCFLAGS='-fpic -dynamic' LDFLAGS='-fpic -dynamic -read_only_relocs suppress'
$ make
for dir in HOC_cbits HOC InterfaceGenerator InterfaceGenerator2 Bindings Foundation AppKit Tools docs ; do (cd $dir; echo "In directory $dir"; make all) done
= snip =
../inplace.conf: openBinaryFile: does not exist (No such file or directory)
make[1]: *** [hocwrap] Error 1
In directory docs
make[1]: Nothing to be done for `all'.
$ ls HOC_cbits | grep HOC
HOC_cbits.o
libHOC_cbits.a
libHOC_cbits.dylib
$ cp HOC_cbits/libHOC_cbits.{a,dylib} HOC_cbits/HOC_cbits.o ~/.cabal/lib
$ runhaskell Setup.hs configure --user
$ runhaskell Setup.hs build
$ sudo runhaskell Setup.hs install
Installing library in /Users/hiromi/.cabal/lib/HOC-1.0/ghc-6.10.4
Installing executable(s) in /Users/hiromi/.cabal/bin
Registering HOC-1.0...
Reading package info from "dist/installed-pkg-config" ... done.
Writing new package config file... done.
~/.ghc/i386-darwin-6.10.4/package.conf を確認。extraLibraries に HOC_cbits が入っていない。修正。
$ cd Bindings $ sudo sh make-bindings-macos.sh *** Processing Framework Foundation *** Parsing Objective-C header files: [ ] = snip = Writing Foundation.pi: 100% [*************************] done. ~/install/hoc/Bindings/Generated/HOC-Foundation ~/install/hoc/Bindings/Generated cabal: These flags are used without having been defined: base4
む。と云うことで、手作業でやってみることにする。
$ cd Generated/HOC-Foundation $ emacs HOC-Foundation.cabal ( 四行目の Flag base を Flag base4 に変更) $ sudo runhaskell Setup.hs configure --user Warning: HOC-Foundation.cabal: A package using section syntax should require "Cabal-Version: >= 1.2" or equivalent. Configuring HOC-Foundation-1.0... $ sudo runhaskell Setup.hs build Preprocessing library HOC-Foundation-1.0... Building HOC-Foundation-1.0... [ 1 of 154] Compiling Foundation.NSXMLNodeOptions ( Foundation/NSXMLNodeOptions.hs, dist/build/Foundation/NSXMLNodeOptions.o ) = snip = Loading package template-haskell ... linking ... done. Loading package HOC-1.0 ... <command line>: can't load .so/.DLL for: HOC_cbits (dlopen(libHOC_cbits.dylib, 9): image not found)
あれ?移した場所が悪かったのかな…… と云うことで:
$ sudo mv ~/.cabal/lib/libHOC_cbits.{dylib,a} ~/.cabal/lib/HOC_cbits.o ~/.cabal/lib/HOC-1.0/ghc-6.10.4
$ sudo runhaskell Setup.hs build
Preprocessing library HOC-Foundation-1.0...
Building HOC-Foundation-1.0...
[ 1 of 154] Compiling Foundation.NSXMLNodeOptions ( Foundation/NSXMLNodeOptions.hs, dist/build/Foundation/NSXMLNodeOptions.o )
= snip =
Loading package template-haskell ... linking ... done.
ghc:
unknown symbol `_setIvarInList'
Loading package HOC-1.0 ... linking ... ghc: unable to load package `HOC-1.0'
こうなった……。うーん。
このIRCログ の 02:04:34 付近をみてみて、HOC/HOC/NewClass.hs の 58行目〜62行目
foreign import ccall "NewClass.h makeIvarList" rawMakeIvarList :: Int -> IO (Ptr IvarList) foreign import ccall "NewClass.h setIvarInList" rawSetIvarInList :: Ptr IvarList -> Int -> CString -> CString -> CSize -> Word8 -> IO ()
を
foreign import ccall "Ivars.h makeIvarList"
rawMakeIvarList :: Int -> IO (Ptr IvarList)
foreign import ccall "Ivars.h setIvarInList"
rawSetIvarInList :: Ptr IvarList -> Int
-> CString -> CString -> CSize -> Word8 -> IO ()
と書き換えて、
$ runhaskell Setup.hs clean $ runhaskell Setup.hs configure --user $ runhaskell Setup.hs build $ runhaskell Setup.hs install
などとして、上書きされてしまうので、再び ~/.ghc/i386-darwin-6.10.4/package.conf を適宜弄ってから、もう一度
$ cd Bindings/Generated/HOC-Foundation $ sudo runhaskell Setup.hs configure --user $ sudo runhaskell Setup.hs build
などとしてみるも、またも unknown symbol `_setIvarInList' と云われる。……むーん……
どなたかこうしてみたら?と云うアドバイスなどありましたらよろしくおねがいします><