2013年6月28日 星期五

Haskell FFI 的使用(簡單版)

Haskell 雖然強大,Haskell platform 也帶有許多相當好用的程式庫,然而有時候你會發現它少了些我們想用,但目前只在 C 語言程式庫找得到的功能,(例如 podofo 的 PDF 讀寫功能, clutter 的動畫功能。)或者是不滿意某個 Haskell 程式庫的設計(freetype2 package 沒有 high level binding),這時就會需要利用到 Haskell 的「外語功能界面」(Foreign Function Interface)來讓 Haskell 取用 C 語言程式庫所提供的獨家功能。

為了目前規劃中的需要,我試著使用了 FFI 來讓我的 Haskell 程式呼叫我的 C 程式碼:HERE!

2013年6月22日 星期六

安裝第二個GHC在系統中

「新的 GHC 支援我想要的那個XX功能了!」但是系統裡面已經有一個 GHC了?「反正人家就是要最新版的 GHC 啦」?這時候你除了等待你的 Linux distribution 提供更新以外,也可以自力更生,把自己想要的 ghc 及所對應的 haskell-platform 打造出來!

2013年6月17日 星期一

想要離線的 haskell 文件哪裡找?

如果說你可能會有一段時間沒辦法用網路,但又想和 haskell 相親相愛...我們可以準備好編譯器、程式庫等的安裝,但說明文件呢? 沒有說明文件的話可是會讓寫程式變得痛苦不堪!(一定會卡住,一直想著想用的到底是哪個 API,函數原型長怎樣,然後到最後只能打草稿...)

和 haskell 一起的經驗應該是快樂的!所以,我們來試著自己做文件吧!

使用cabal

(出處:見 這裡

如果你相當把握你只會使用某些 package,那就在還可以用網路的時候使用 cabal 來製作文件吧。cabal 預設不會幫你建立文件,所以你必須修改 ~/.cabal/config。打開它,找到以下這行:

-- documentation: False
然後改成
documentation: True
然後重新安裝你想要文件的 package 。須注意重新安裝很多package可能會相當危險。 (這裡 有重新安裝除了 base 以外所有 package 的方法)

想要 ghc runtime library 的相關文件的話,請見下面「下載所有 haskell package」部份的 libraries.html.tar.bz2

使用這個方法建立文件的話,會有個文件索引在~/.cabel/share/doc/index.html

離線建立文件

如果說你沒把握你只會玩弄某幾個 package,而希望可以保險一點的話,那麼就想辦法把整個 hackage 裡的所有 package 都下載下來不就好了?

下載所有的 haskell package

我們會需要下面的所有東西:

  • GHC 文件下載區選正確的版本,然後下載:
    • haddock.html.tar.bz2
    • libraries.html.tar.bz2
    • users_guide.html.tar.bz2
  • Hackage 下的 Getting the raw data,或是 下載整個Hackage archive(使用wget)
如果下載的是 Getting raw data 中的 00-archive.tar, 則:
mv /path/to/00-archive.tar /tmp
cd /tmp
mkdir hackage
cd hackage
tar -xf ../00-archive.tar
每個對應的 haskell package 就會存在/tmp/hackage/PACKAGE_NAME/VERSION/PACKAGE_NAME-VERSION.tar.gz

建立文件(相依套件已存在)

文件下載好後,我們利用下面的步驟來建立文件

# in /tmp
mkdir build
cd build
tar -xf ../hackage/array/0.4.0.1/array-0.4.0.1.tar.gz
runhaskell Setup configure --builddir=./array-build --user
runhaskell Setup build --builddir=./array-build
runhaskell Setup haddock --builddir=./array-build
# 完工\^o^/ ,去./array-build/doc 找做好的文件
# 想順便安裝的話...
runhaskell Setup install
# 安裝完後,也可以在 ~/.cabal/share/doc 下找到做好的文件。
另外一種方法:
mkdir build
cd build
tar -xf ../hackage/array/0.4.0.1/array-0.4.0.1.tar.gz
cabal configure
cabal haddock
# 此時文件會在 dist/doc/html 中
# 如果想要安裝起來,那就再執行:
cabal install

如果相依套件不存在,就找到相依套件,然後使用這裡的步驟把所有的相依套件安裝起來吧!

建立文件(相依套件未存在且不想安裝)

假如你不想安裝建置好的程式庫(?),那麼你可以考慮利用這裡的方式,暫時把相依套件建立在某個暫存區內。

假設我們想安裝zip-archive, 結果發現:

$ runhaskell Setup configure --builddir=../build --user
Configuring zip-archive-0.1.3.4...
Setup: At least the following dependencies are missing:
digest >=0.0.0.1, utf8-string >=0.3.1
$ 
那就試試這裡的步驟吧!
(相依性資訊記載於下載下來 package 的 tar.gz 中的 .cabal 檔中的 Build-depends 內)

# in /tmp
$ mkdir build
$ cd build
$ # 解開包裹
$ tar -xf ../hackage/utf8-string/0.3.7/utf8-string-0.3.7.tar.gz
$ tar -xf ../hackage/digest/0.0.1.2/digest-0.0.1.2.tar.gz
$ tar -xf ../hackage/zip-archive/0.1.3.4/zip-archive-0.1.3.4.tar.gz
$ # 設定暫存位置
$ mkdir packages # package 暫存區
$ mkdir tmp # build 暫存區
$ # 設定暫時 package 註冊區
$ ghc-pkg init package-db
$ # utf8-string 0.3.7
$ cd utf8-string-0.3.7/
$ runhaskell Setup configure --builddir=../tmp/utf8-string\
 --prefix=`pwd`/../packages --package-db=../package-db
Configuring utf8-string-0.3.7...
$ runhaskell Setup build --builddir=../tmp/utf8-string
Building utf8-string-0.3.7...
Preprocessing library utf8-string-0.3.7...
# 編譯過程,略
$ runhaskell Setup haddock --builddir=../tmp/utf8-string
Running Haddock for utf8-string-0.3.7...
Preprocessing library utf8-string-0.3.7...
Warning: The documentation for the following packages are not installed. No
links will be generated to these packages: rts-1.0
Haddock coverage:
 100% (  8 /  8) in 'Codec.Binary.UTF8.String'
  94% ( 16 / 17) in 'Codec.Binary.UTF8.Generic'
  89% ( 24 / 27) in 'Data.String.UTF8'
  82% ( 14 / 17) in 'System.IO.UTF8'
  14% (  1 /  7) in 'System.Environment.UTF8'
 100% ( 17 / 17) in 'Data.ByteString.UTF8'
 100% ( 17 / 17) in 'Data.ByteString.Lazy.UTF8'
Documentation created: ../tmp/utf8-string/doc/html/utf8-string/index.html
$ runhaskell Setup install --builddir=../tmp/utf8-string
Installing library in
/tmp/build/utf8-string-0.3.7/packages/lib/utf8-string-0.3.7/ghc-7.4.1
Registering utf8-string-0.3.7...
$ cd ..
$ # digest 0.0.1.2
$ cd digest-0.0.1.2
$ runhaskell Setup configure --builddir=../tmp/digest --prefix=`pwd`/../packages --package-db=../package-db
Configuring digest-0.0.1.2...
$ runhaskell Setup build --builddir=../tmp/digest
Building digest-0.0.1.2...
Preprocessing library digest-0.0.1.2...
[1 of 2] Compiling Data.Digest.Adler32 ( ../tmp/digest/build/Data/Digest/Adler32.hs, ../tmp/digest/build/Data/Digest/Adler32.o )
[2 of 2] Compiling Data.Digest.CRC32 ( ../tmp/digest/build/Data/Digest/CRC32.hs, ../tmp/digest/build/Data/Digest/CRC32.o )
In-place registering digest-0.0.1.2...
$ runhaskell Setup haddock --builddir=../tmp/digest
Running Haddock for digest-0.0.1.2...
Preprocessing library digest-0.0.1.2...
# 建立文件訊息,略
Documentation created: ../tmp/digest/doc/html/digest/index.html
$ runhaskell Setup install --builddir=../tmp/digest
Installing library in
/tmp/build/digest-0.0.1.2/../packages/lib/digest-0.0.1.2/ghc-7.4.1
Registering digest-0.0.1.2...
$ cd ..
$ # zip-archive
$ cd zip-archive-0.1.3.4/
$ runhaskell Setup configure --builddir=../tmp/zip-archive --prefix=`pwd`/../packages --package-db=../package-db
Configuring zip-archive-0.1.3.4...
$ runhaskell Setup build --builddir=../tmp/zip-archive
Building zip-archive-0.1.3.4...
Preprocessing library zip-archive-0.1.3.4...
[1 of 1] Compiling Codec.Archive.Zip ( src/Codec/Archive/Zip.hs, ../tmp/zip-archive/build/Codec/Archive/Zip.o )
In-place registering zip-archive-0.1.3.4...
$ runhaskell Setup haddock --builddir=../tmp/zip-archive
# 建立文件訊息,略
$ runhaskell Setup install --builddir=../tmp/zip-archive
Installing library in
/tmp/build/zip-archive-0.1.3.4/../packages/lib/zip-archive-0.1.3.4/ghc-7.4.1
Registering zip-archive-0.1.3.4...

這樣就完成了呢!這時候文件會存放在/tmp/build/packages/share/doc/裡面,然後你就可以開始閱讀他們了!

2013年6月16日 星期日

解壓縮zip檔案:當中文字變成亂碼之二

前情見上一篇。 弄了一天多,總之弄出了可以用的東西(在這裡,想要看程式碼的人,歡迎光臨!)。

2013年6月15日 星期六

解壓縮zip檔案:當中文字變成亂碼

最近學習haskell中,想要拿幾個文字檔來練習IO以及資料處理。首先試著找"open data taiwan",想看有沒有台灣政府提供的政府資料。找著找著,找到了經濟部能源局的資料。點了第一個下來,開始準備解壓...檔名是亂碼Orz

雖然可以猜得出檔名應該是「國際原油價格.csv」,但對於處理內有中文檔名的壓縮檔已經不是第一次了。我想要一口氣解決它!(然後haskell之夜就泡湯了Orz,詳下)

搜尋發現了一些解決方案,包括了「unzip -O」(我的unzip沒有這個選項),「LANG環境變數+7za」(出來還是亂碼)。我想要一個可以解壓縮,然後一邊更改檔案名稱編碼的解壓縮程式,不過目前看起來能夠符合我條件的解壓縮程式似乎不存在,所以只好自己來做一個簡易版的。

我首先考慮了正在練習的haskell,但是,就在我腦袋閃過了python的解決方法後,我決定先用python試一下,然後...就結束了?(程式碼見此

那個python的解決方案使用了python 2.x,而不是python3。仔細一瞧,python3 的 zipfile 模組傳回的檔名字串似乎沒辦法轉換成原本在zip檔中的原始字串(raw string,原汁原味的那個字串),所以沒辦法像在python 2.x裡那樣子做編碼轉換。

鑑於python沒機會了,我想依賴haskell看看。在hackage中搜尋之後,我猜使用zip-archive, iconv,再配合上bytestring這三個package應該就可以完成目標了:使用Data.ByteString.Lazy.Char8 的 pack, Codec.Text.IConv 的 convert 應該就可以順利的進行轉換。現在有點晚了,明天再來試試看。

每次看到別人說 haskell 只是學術界教授們在用的程式語言,我都覺得很傷心:明明有那麼多的 package,這麼有趣的語法...。因此,我衷心的希望我可以利用這次機會來證明 haskell 不只是象牙塔裡的玩具,因此我會加油的!

2013年6月1日 星期六

所謂的執法

很令人訝異的,最近台灣發生的一些大事都和執法有關。

首先來說說已經有點久的廣大興28號漁船攻擊事件。這起攻擊事件喚起了許多國人的愛國意識,並且理性的(我們不過把軍艦開到經濟海域逛幾圈對吧?)追求屬於我們的那份正義。

簡單的說,有個漁民在有爭議的經濟海域捕魚,被菲律賓海巡隊釘上並遭到強烈火力的攻擊,漁民洪石城先生在此攻擊中不幸喪生。廣大興28號回港後,我國政府給菲律賓政府72小時 (也就是三日)通牒,希望菲國政府為此事件道歉,並且啟動公平的調查;然而,未把台灣當成一個國家來看待的菲國打算敷延了事,讓台灣人民群情激憤。在夾帶民意的支持下, 我國政府行使了主權國家才有的權力,祭出了許多項包括經濟以及外交方面的制裁,並且(稍稍的)利用軍隊施壓。此時國際輿論對於此事件大多偏向憐憫菲律賓,所幸在眾多鄉民們的努力之下 ,國際輿論終於看清菲律賓政府執法過當之事實。現在,調查的結果強烈的指出菲國海巡隊執法過當,濫用火器才導致本次事件的發生。

這個事件起初不是相當明朗。例如說,我們不知道漁船有沒有試圖衝撞海巡隊的鐵船(雖然看就知道..嗯..),也不知道漁船有沒有不服對方海巡隊的指示(客觀來說,只憑著我方漁民的說詞 是不夠的。當然我相信他們的清白),然而事實很清楚:就算我們的漁船真的犯下了一些錯,菲國執法單位,依據國際法,也沒有權力使用軍用等級的槍械來掃射手無寸鐵的漁民。

接著的兩個事件都是本週內的。

第一個是智慧財產局(智財局)宣佈要實施的「封鎖境外侵權網站」的措施。依據該局的說法,若某境外網站有「一望即知」的侵權現象,則將在邀集各方人士開會後利用IP協定(或從DNS移除該網站網址的對應IP)封鎖該網站。此措施為人詬病的地方是,若該法案通過,則將會賦予政府機關未經法院判決而得以限制人民閱聽目標網站的權利。此外,此法案等於是為了守護少數人之利益,而侵犯大眾的,受憲法保障的祕密通訊自由。在美國,利益團體邀請國會議員推行類似的法案SOPA(和台灣的差別?封網站前要先經過法院。)受到各界,包括白宮、維基百科、以及世界各大網站的強烈反對,最後在國會中難產。

我相當的希望這個無論在技術上、法理上都站不住腳的法案不要通過。一旦這個法案通過了,我國的言論自由將會嚴重的後退。到時有心人士會不會利用這個法案來封鎖我們喜愛的境外網站呢?(莫須有的侵權)我們以後還可以下載GNU/Linux, 看CNN或經濟學人嗎?(相信大家都懂的>_^)即使封鎖網站會經過法院的審理,大家都知道因為侵權材料而封鎖一個IP,就跟有人擺攤賣假包包就命令整條街道禁止營業一樣的扯。

最後是非常令人傷感的,一位好醫師(願意投身於愛滋病人長期照護的醫師現在已經不多了)因為一個「只」喝了半瓶伏特加,自以為沒有醉的人給撞成重傷了。該醫師的指導老師柯文哲醫師除了心痛外,也呼籲類似的事件(也就是酒後駕駛)不要再發生了。現在各界人士都希望奇蹟可以出現,讓這位醫師得以回來繼續實現她的夢想。

雖然這個事件描述是三者最短的,但也是最令人感到哀傷的一個。這個事件也讓我聯想到葉少爺酒駕事件,以及那個破碎的,再也回不來的家庭。

此時立院修法通過加重酒後駕駛的刑期,然而修法後的條文也不過就是加重了刑期而已。那些酒後開車的人沒有顧及他人的生命(明知道開車上路會不穩,會撞到人),開車上路已經可以說是殺人未遂了;如果真的很不幸撞死了人,那怎麼不用殺人罪去法辦呢?這樣至少比本次事件的「三萬元交保」還要符合比例原則!

菲國政府願不願意把兇手引渡來台灣受審,基於國際情勢,是個未知數,但至少我們現在已經還漁民一個清白了。之所以可以討論此事件,並在菲國利用國際輿論來抹黑我國的同時由許多偉大的鄉民串連在國際上發聲,憲法賦予我國的言論自由絕對功不可沒(沒了這個我們可不能批評我們的政府軟弱無能)。然而,我們可貴的言論以及祕密通訊的自由有可能會受到賦予制裁局封鎖網路權力(為了保障少數人)的惡法威脅,在此同時,我們的法律卻又無法保護許多認真的,默默為了夢想而付出的人們。

我不禁想,除了流眼淚之外,我還可以做什麼...