(2005.7.18 新規作成, 2009.1 更新。)
関数型プログラミングのための言語 Haskell について。
次のメモはC++メインですが、前半でHaskellのMaybeモナドを解説しています。
(2008.11.7 この節を追加。)
例えばC言語でもオブジェクト指向プログラミングができます(gtk+など)が、プログラミング言語の支援があったほうが自然にプログラミングできます。
Haskell, あるいはほかの関数型プログラミング言語 (O'Caml, Concurrent Clean, Erlang など)は、関数型プログラミングを支援します。
関数型言語は、おおむね、
変数とオブジェクトの書き換えをおこなわないことで、平行処理が容易にできる可能性があります (concurrent computing)。
Haskellは、上の特徴に加えて、式が遅延評価(lazy evaluation)されます。例えば、リストで最初の5要素しか必要でなければ、6番目以降の要素はそもそも計算されません。
(2008.11.8 この節を更新。)
Haskellでプログラムを作るには、コンパイラかインタプリタを用意します。次のようなものがあります。
実用では今のところ、GHCしか選択肢がないように思います。
クライアントアプリケーションを作るときは GUIライブラリも必要です。こなれているのは次の二つだと思います。
ここではgtk2hsをインストールしてみます。
Windowsの場合は、先に MinGW 環境を整えます。MinGWのインストールは MinGWのインストール を参照してください。
次にGHCをインストールします。2008.11 現在、安定版の最新版はバージョン6.10.1です。
Windows用にバイナリ版が用意されているのでそれを利用します。インストーラをダウンロードしてきて実行します。
次はgtk2hsです。
gtk2hs は gtk2ライブラリを必要とします。先に Windowsネイティブなgtk2アプリケーションの開発 を参考に、インストールしておきます。
2008.11現在、Gtk2Hs の最新版はバージョン0.9.13です。
これもWindows用にバイナリ版が用意されています。インストーラをダウンロードして実行します。
Fedora 9 Linux には次のパッケージが用意されています。yum (または yumex) でインストールします。
GHCが最新の6.10.1ではないですが、最初は6.8.2でも問題ないと思います。
(2008.11.9 この節更新。)
まずはお約束のはろーわーるどから。
Haskellソースはファイル名の拡張子を .hs にします。GHCでは、文字コードはUTF-8 限定です。UTF-8以外の場合、コメント以外の場所に書けるのはASCIIだけです。
文字列リテラルは内部ではUnicodeで保持されますが、入出力の文字コードを指定する方法は、組み込みでは用意されていないようです。GHC 6.8.2 だと、UTF-8でも出力できなくて、ちょっと泣けます。
追加ライブラリについては、このあたりを参照; blog.kfish.org: Survey: Haskell Unicode support
さて、ハローワールドですが、こんな感じです;
コンパイルはghcコマンドです。オプションを何も付けないとリンクまでおこないます。コンパイルに成功すると a.out が出力されます。
$ ghc first.hs
GHCには、インタプリタGHCiが付属している。ghciコマンドで起動できる。抜けるのは:quit。
$ ghci ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base-1.0 ... linking ... done. Prelude> 1 + 2 * 3 7 Prelude> "abc" ++ "def" "abcdef" Prelude> [1] ++ [4] [1,4] Prelude> [1] ++ [2,3] [1,2,3] Prelude> :quit Leaving GHCi.
Haskellの予約語は、
case | class | data | default | deriving | do | else | if | import | in | infix | infixl | infixr | instance | let | module | newtype | of | then | type | where | _
これだけ。大文字・小文字を区別する。
Haskell では、関数の名前が同じで引数が違うものを複数定義できる。
次のスクリプトは、リストの値を順番に表示する。
[]は空リスト、[x..y]は、xからyまでの値を含むリスト。[1..]と書くと、1以上無限の値を含むリストになる。
関数fooをオーバーロードし、空リストのときは上の関数を実行し、そうでないときは下の関数を実行する。
x:xsの「:」は演算子で、最初の引数を二つ目の引数であるリストの前に加える。関数の引数としては、リストを先頭の値xと残りのリストxsに分ける。
showは値を文字列に変換する(表示用)。
main = putStrLn (foo [1..]) foo [] = "" foo (x:xs) = (show x) ++ "\n" ++ foo xs
何気なく無限リストを作ったが、エラーにならずに表示できる。
(2005.9.3)
関数を定義するとき、引数のパターンマッチで書く以外に、条件式でどの定義を使うかを選択するようにできる。
次のサンプルは階乗を計算する。
factorial :: Integer -> Integer -- 関数宣言 factorial 0 = 1 factorial n = n * factorial (n - 1) main = putStr (show (factorial 10))
これは、次のようにも書ける。その他の場合の定義は、| otherwise = ... と書く。
factorial n | n == 0 = 1 | n > 0 = n * factorial (n - 1)
関数をつなげる (.) や ($) も関数(演算子)です。
Haskellスクリプトをコンパイルして実行したときに、コマンドラインオプションを取れるようにしたい。
do ... は、手続き型言語のように上から順に実行する。<- は変数に代入する。
import System -- getArgs
main = do
args <- getArgs -- argsは[String]型になる
-- x <- getLine と書くと、コンソールから読み込む
putStrLn (show args)
実行結果はこう。
$ ./main.exe foo bar --list=hoge ["foo","bar","--list=hoge"]
|
ふつうのHaskellプログラミング -- ふつうのプログラマのための関数型言語入門 (2007.1.19) Haskellの初歩から文法、勘所まで着実、丁寧に解説した、非常に優れた本。これを読めばHaskellを読み書きできるようになること間違いなし。 Haskellの考え方に触れることで、Java / C++ / Ruby / Pythonなどほかのプログラミング言語でプログラミングするときでも再利用しやすく、保守しやすいコードを書く参考になる。 お薦め。 |
Netsphere Laboratories http://www.nslabs.jp/
[PR]