Haskell(GHC)で記号プログラミング

tag sym

oskimuraです。
HaskellというかGHC固有なのですが、実はGHCってcppオプションを使う事によってプリプロセッサを展開してくれます。(発見者はid:ranhaさんです)
なので、これを利用して記号プログラミングで"HELLO WORD!"を出力してみます。

#define _ 1
#define __ main=print

1の定義とプリプロセッサを通す上でmain関数を呼ばなきゃいけないのでこうしました。

数値を文字列に変換するためにData.Charモジュールのchr関数を使いたいので、次の様にしました。

import Data.Char(chr)
(%%) = chr

これで(%%)を使ってASCIIコードを文字に変換できます。
ここまでくるともう簡単ですねHelloWorldの本文を書いてみたいと思います

(&&&)   = (_+_+_+_) ^ (_+_+_)               -- 64
(@@)   = (&&&) + (_+_) ^(_+_+_)             -- H
(@@@)  = (&&&) + (_+_+_+_+_)                -- E
(@@@@) = (&&&) + (_+_+_+_) * (_+_+_)        -- L
(@@@@@) = (&&&) + (_+_+_) * (_+_+_+_+_)     -- O
(@@@@@@) = (_+_) ^ (_+_+_+_+_)              -- [SP]
(@@@@@@@) =  (_+_+_)^(_+_+_+_)+(_+_+_)*(_+_)-- W
(@@@@@@@@) =  (_+_+_)^(_+_+_+_)+_           -- R
(@@@@@@@@@) = (_+_+_+_) ^ (_+_+_) + (_+_+_+_) * (_*_*_)  -- D
(@@@@@@@@@@) = (_+_+_) ^ (_+_+_) + (_+_+_) * (_+_) -- !

__ [(%%)(@@), (%%)(@@@),(%%)(@@@@),(%%)(@@@@),(%%)(@@@@@),(%%)(@@@@@@),(%%)(@@@@@@@),(%%)(@@@@@),(%%)(@@@@@@@@),(%%)(@@@@),(%%)(@@@@@@@@@),(%%)(@@@@@@@@@@)]

ASCIIコードを定義して数字に変換したものをリストにいれ、文字列としてあつかっているだけです。(Haskellで文字列は文字のリストです)
__は上で定義したmain = printですね。
つまり、このコードは次のコードと等価です。

main = print "HELLO WORLD!"

このように -cppオプションを付けて実行してみてください。

ghc -cpp symbolic.hs && ./a.out

ね、簡単でしょ。


ArrowやApplicativeを組み合わせるともっと記号記号したいろんなプログラミングが書けると思います。腕に自信のあるHaskellerは挑戦してみてください。
仕事でHaskellを使う機会があったら、みなさんもぜひ今回紹介したテクニックを使ってみてください。