2012-02-20
■[haskell]cgenを試してみた
cgenとはC++をHaskellから呼び出すためのヘルパープログラムです。
http://anttisalonen.github.com/cgen/
C++はC言語と違ってシンボル名がマンドリングされているので、そのままでは呼び出せません。
その解決の方法として、C言語のラッパを書く必要があります。
cgenはそのCのコード自動生成するプログラムです。
インストール
cabal install cgen
Cコード生成
cgenはc++ヘッダーファイルからcのヘッダーとソースファイルを作成します。
$ cgen -o c --header=Animal.h --header=Dog.h \
--header=Sheep.h cpp/Dog.h cpp/Sheep.h cpp/Animal.h
C++継承グラフ作成
grgenコマンドでc++のソースから継承グラフを表現するファイルを作成します
$ grgen -o graph cpp/Animal.h cpp/Dog.h cpp/Sheep.h
Haskellコード生成
先程の継承グラフとCのヘッダからHaskellコードを生成します
grgen -o graph cpp/Animal.h cpp/Dog.h cpp/Sheep.h
ghcリンク
最後にcのコードから生成したオブジェクトファイルとHaskellコードをコンパイル・リンクします。
$ ghc --make -o Main -L. -lanimals -lstdc++ Main.hs
サンプルプログラムはこちらです。
2012-02-11
■[haskell]GHCソースコードリーディング勉強会 第0回(準備編)に参加しました
http://partake.in/events/57179633-b2ad-4e7d-b56e-c4ac8e6b178e
リンク集がわりに
- GHC Commentary: The Compiler
http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler
- Compiling one module: HscMain
http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/HscMain
- 岡部さんの資料
http://wiki.haskell.jp/Workshop/ReadGHC/0
http://d.hatena.ne.jp/suztomo/20111224/1324718354
- I know kung fu: learning STG by example http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GeneratedCodeTracing
- the compilation of Hello Factorial!
http://blog.ezyang.com/2011/04/tracing-the-compilation-of-hello-factorial/
- Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine - Version 2.5 (1992)
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.3729
- The Implementation of Functional Programming Languages http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/
- Implementing functional languages: a tutorial http://research.microsoft.com/en-us/um/people/simonpj/papers/pj-lester-book/
- How to make a fast curry: push/enter vs eval/apply
http://research.microsoft.com/en-us/um/people/simonpj/papers/eval-apply/
- GHCのこと
http://www.kotha.net/hperf/ghc.html
Core言語の操作的解釈
http://www.haskell.org/ghc/docs/7.4.1/html/libraries/ghc-7.4.1/
2012-01-27
■[Haskell] Conduitのトリビアルでシンプルなサンプル
Haskellの新しいIOライブラリのトリビアルなサンプルを書きました。
Conduitとは、水道管とか溝とか言う意味です。
この例は読み込みと書き込みのファイルを開いて10文字だけコピーするだけのサンプルです
do構文で組み立てられたResourceTモナドをrunResourceで実行とモナド変換を行います
このdo構文の中は大まかに分けて3つとなります。
- リソースの確保
- パイプ処理
- リソース開放
リーソスの確保
(srcKey, rHandle) <- with (openFile src $ ReadMode) $ hClose
withを使ってリソースを確保します。
withの第一引数が確保。第二引数が開放のためです。
それぞれコンストラクタとデストラクタのようなものです。
withの返り値はタプルとなっています。このタプルの一番目がキーとなっており開放のために使います。二番目はハンドルとなっており、パイプ処理の時にSource,Sinkに変換して使います。
with定義
withSource :: Resource m => Base m aallocate -> (a -> Base m ())free resource -> ResourceT m (ReleaseKey, a)
パイプ処理
ResourceTを組み立てる必要があります。
そのために
source -> conduit -> sink
(unixの例えでばよけばcoduitはパイプ"|")
というパイプを作り必要があります。
この例の場合
(sourceHandle rHandle) $= (isolate 10) $$ sinkHandle wHandle
該当箇所となります。
- source
sourceHandle rHandle
sourceHandle定義
sourceHandle :: ResourceIO m => Handle -> Source m ByteString
- conduit
(isolate 10)
- sink
sinkHandle wHandle
sinkHandle定義
sinkHandle :: ResourceIO m => Handle -> Sink ByteString m ()
となります
sourceHandle, sinkHandleはそれぞれハンドルをsource、sinkに変換する関数です。
($=)演算子はConduitを結合するための演算子です。
こうして作られたパイプコンビネータ($$)ResourceT組み立てます。
isolate定義
isolate :: Resource m => Int -> Conduit ByteString m ByteString
($$) 定義
($$) :: (IsSource src, Resource m) => src m a -> Sink a m b -> ResourceT m b
($=)定義
($=) :: (IsSource src, Resource m) => src m a -> Conduit a m b -> Source m b
リソース開放
リソースの開放release関数を使って行われます
release srcKey
release定義
release :: Resource m => ReleaseKey -> ResourceT m ()
2010-12-08
■[Haskell]HappStackでエラー
HappStackっていうHaskellのWeb Frameworkがあるんだけど、
これのチュートリアルをみながらコードかいてたんだけど、エラーがでてコードが通らない。
http://happstack.com/docs/crashcourse/Templates.html#helloblaze
HappStackでblaze-htmlっていうテンプレートライブラリ使うみたいだけど、No instanceとか言われる
import Control.Monad
import Data.Char (toLower)
import Happstack.Server (Method(GET,POST,HEAD),methodM,FromReqURI(..),nullConf, simpleHTTP, toResponse, ok, dir, path, ServerPart, Response)
import Text.Blaze ((!))
import qualified Text.Blaze.Html4.Strict as H
import qualified Text.Blaze.Html4.Strict.Attributes as A
appTemplate :: String -> [H.Html] -> H.Html -> H.Html
appTemplate title headers body =
H.html $ do
H.head $ do
H.title (H.string title)
H.meta ! (A.http_equiv (H.stringValue "Content-Type")) ! (A.content (H.stringValue "text/html;charset-utf-8"))
sequence_ headers
H.body $ do
body
helloBlaze :: ServerPart Response
helloBlaze =
ok $ toResponse $
(appTemplate "Helloblaze!"
[H.meta ! (A.name (H.stringValue "keywords")) ! (A.content (H.stringValue "http blaze"))]
(H.p . H.string $ "helloblaze!"))
コードは上記な感じ
エラーはこんな感じ
No instances for (Data.Generics.SYB.WithClass.Basics.Data
happstack-data-0.5.0.3:Happstack.Data.Xml.Base.XmlD
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()),
Happstack.Data.Default.Default
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()),
Data.Generics.SYB.WithClass.Basics.Data
Happstack.Data.Normalize.NormalizeD
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()))
arising from a use of `toResponse'
at /Users/oskimura/Downloads/HelloWorld.hs:45:9-18
Possible fix:
add an instance declaration for
(Data.Generics.SYB.WithClass.Basics.Data
happstack-data-0.5.0.3:Happstack.Data.Xml.Base.XmlD
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()),
Happstack.Data.Default.Default
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()),
Data.Generics.SYB.WithClass.Basics.Data
Happstack.Data.Normalize.NormalizeD
(blaze-html-0.2.4.0:Text.Blaze.Internal.HtmlM ()))
In the first argument of `($)', namely `toResponse'
In the second argument of `($)', namely
`toResponse
$ (appTemplate
"Helloblaze!"
[H.meta ! (A.name (H.stringValue "keywords"))
! (A.content (H.stringValue "http blaze"))]
(H.p . H.string $ "helloblaze!"))'
In the expression:
ok
$ toResponse
$ (appTemplate
"Helloblaze!"
[H.meta ! (A.name (H.stringValue "keywords"))
! (A.content (H.stringValue "http blaze"))]
(H.p . H.string $ "helloblaze!"))
Failed, modules loaded: none.
Generics関連のエラーだと思うけど原因はよく分からない。
ghcのバージョンは6.12.1
happstackは0.5.0.3
blaze-htmlは0.2.4.0
2010-10-05
■[Haskell] Project Euler Problem 97 はHaskellなら一行
http://d.hatena.ne.jp/aomori-ringo2/20101004/1286183347
をみてHaskellなら簡単に書けそうだなと思って書いてみたら一行だった…
euler97 = reverse . (take 10) . reverse . show $ (28433*2^7830457+1)
結果はこちら(答えがあるので閲覧は注意)

