約 2,107,918 件
https://w.atwiki.jp/mamonbo/pages/18.html
この章に出てくるすべての例はHaskellのソースファイルに入力しGHCないしHugsに読み込ませることで評価することができる。入力の頭の Prelude のプロンプトは含めないこと。プロンプトが出ているときは、GHCiといった環境にコードを入力してよい。そうでない時は、コードをファイルに入れて実行すること。 (斜体にするのは英字だけみたい。そしてEnter入ると切れるみたい。) 変数 GHCiを電卓として使う方法はもう見た。もちろん、この方法は短い計算に取ってのみ実用的である。より長い計算やHaskellのプログラムを書くのには中間結果を追跡したい。 中間結果は変数に格納でき、名前で呼び出すことができる。1つの変数には1つの値が入っていて、変数が使われた時に変数名が値に代わる。例えば、以下に示すような計算である。 ghci 3.1416 * 5^2 78.53999999999999 これは円の面積公式A = \pi r^2による半径5の円のおよその面積である。\pi (\approx 3.1416)の数桁打つのも、この数桁をきっかり覚えるのさえも面倒臭い。実際、プログラミングの重要な気の持ちようの1つは我々の頭が思う存分より面白い考えを扱うようにするために、非思考的な繰り返しや丸暗記を機械に任せることだ。今回の場合なら、Haskellはすでに10桁以上の\piを格納しているpiという変数が入っている。 ghci pi 3.141592653589793 ghci pi * 5^2 78.53981633974483 注意 変数piとそれが持っている値3.141592653589793は計算上では相互交換可能に使われうる。 (後ろに9が続くのは10進数で有限小数でも2進数では無限小数なために精度落ちするため。 ちなみに私は3.14159265358979323846264338327950288419716939937510まで覚えている) Haskellのソースファイル 一瞬だけ使うわけでないコードを書くときはいつでも、コードを拡張子が.hsのHaskellのソースファイルに保存する。基本的に、.hsファイルはプレーンテキストである。 テキストエディタにコーディングに合った予測機能が必要ならWikipediaのテキストエディタの記事から始めてみるのが良いだろう。VimやEmacsがHaskellプログラマの間でよく採用されている。(小生Emacsユーザーなのです、スミマセン) しっかりとしたソースコードエディタには読解を楽にするために適切にでコードに色を付ける構文ハイライトが付いている。 きちんと管理するためにこの本での演習で作ることになるHaskellファイルを保存するためのディレクトリ(Windowsで言うところのフォルダ)を作っておくこと。このディレクトリをHaskellWikibookなりと呼ぶことにする。そしてそのディレクトリ内にVarfun.hsという名前のファイルを作り以下のコードを書く r = 5.0 このコードは変数rを5.0と定義している。自分で変数を設定すると後の計算をするのが容易になる。 注意 行頭にスペースが入っていないことを確かめること、というのもHaskellはスペースに厳格なのである。 次に、ターミナルをHaskellWikibooksディレクトリに持って行き、GHCiを起動し loadコマンドを使ってVarfun.hsファイルを読みこむ Prelude load Varfun.hs [1 of 1] Compiling Main ( Varfun.hs, interpreted ) Ok, modules loaded Main. loadは lと略せる。(今回なら l Varfun.hsのように略せる) もしGHCiがCould not find module Varfun.hs ( Varfun.hs モジュールを見つけられませんでした)といったエラーを出した場合、違うディレクトリにいる可能性がある。 cdコマンドでGHCiの中でディレクトリを変えることが出来る。(例えば、 cd HaskellWikibook) ファイルがロードされたのなら、新しく定義した変数rを計算に使うことが出来る。 *Main r 5.0 *Main pi * r^2 78.53981633974483 なので、半径5の円の面積を計算するために、単にr = 5.0と定義して、よく知られている円の面積公式\pi r^2を入力する。これにより毎回数を書く必要が無くなり、とても便利である。 この機能はとても便利だったので、更に定義を加えよう ソースファイルの内容以下のように変更する。 r = 5.0 area = pi * r ^ 2 ファイルを保存し、新たな内容を読みこませるために reload(省略形は r)コマンドをGHCiに入力する。(このことはこのページの最後まで続く) *Main reload Compiling Main ( Varfun.hs, interpreted ) Ok, modules loaded Main. *Main 今、rとareaの2つの変数が利用可能である。 *Main area 78.53981633974483 *Main area / r 15.707963267948966 注意 GHCiプロンプトからソースファイルを使わずに直接変数を定義することも可能である。詳しいことを省略すると、これをするための構文はletというキーワード(特別な意味を持つ語、変数名や関数名として使うことが出来ない)を使う。 (小生は予約語と習ったがキーワードというのが最近の流行りなのだろうか) 例えば以下の通り Prelude let area = pi * 5 ^ 2 便宜上このようにletを時々使うが、このやり方は一旦少しでも複雑な仕事に移ると不便である。そのため、最初からソースファイルを使うことを強調している。 (letは数学な世界で仮定の意味だと思われ、BASICにもだいたい省略可能でLETはある) 注意 GHCはコンパイラとしても利用可能である。(つまり、自分の書いたHaskellファイルをインタプリタに頼らずに実行できるスタンドアロンプログラムに変換するためにGHCを使うことが出来る。)やり方についてはスタンドアロンプログラムの章で後々説明する。(Glasgow Haskell Compilerですから出来なきゃ詐欺) コメント 続きに行く前に、プログラム内に文章をコードとして扱われずに入れることが可能であることを理解するのが良い。これはコメントを使うことによって出来る。Haskellではコメントは-- で始め、行の最後まで続く x = 5 -- 変数xは5 y = 6 -- 変数yは6 -- z = 7 この場合、xとyは定義されているが、zは定義されていない。さらに、コメントは代わりの構文{-(コメント)-}を使うことでどこにでも入れることも出来る。(日本語も可能) x = {-可能だからというだけの理由でやっている-} 5 一般にコメントは読者が混乱するかもしれないプログラムの部分を説明するのにその場所に使われる。 しかしながら使いすぎには注意すること。コメントが多すぎるとプログラムが読みにくくなる。 また、対応するコードを変更した時はコメントが古いのになったり、不正確であったり、間違いを引き起こしがちにならないようにいつもコメントを注意深く更新すること。 命令型言語での変数 もしCのような命令型プログラミング言語に既に慣れているのなら、Haskellの変数があなたの知っている変数というものととても異なっていることに気付くことになる。では今からその理由と違いについて説明してゆく。 もしプログラミング経験がないのなら、この部分を読み飛ばして関数(うまく動作しせん)から読むのが良いかもしれない。 命令型言語の場合と異なり、Haskellでの変数は不変である。(←重要 斜体が出ないので) つまり、一度定義すると、中の値は決して変化しない、イミュータブルなのである。例えば、以下のコードは動かない r = 5 r = 2 関数型プログラミング言語での変数は計算機のメモリの位置というよりも数学的な変数の方がより関連している。数学の授業では一つの問題の中で絶対に決して変数の中の値が変わることは無かっただろう。それ同様に、Haskellではコンパイラは上のコードに対し multiple declarations of r (rの多重宣言)とエラーを返すのだ。 計算機に何をするかを明示的に伝えることがある命令型プログラミングに慣れている人々にとってはこれを「最初r = 5と設定して、次にr = 2と変える」 と読むのに慣れているかもしれない。しかしながら、関数型プログラミングでプログラムは計算機のメモリで何をするのかを明らかにする責任がある。 これは命令型言語との大きな違いの別の例である r = r + 1 これは(命令型言語で考えがちな) 変数rのインクリメント ではなく、 実際はそれ自身の観点では、rの再帰的定義である。(詳しくは再帰を後々説明する。命令型言語で起こるようなことと大きな違いがあることだけを覚えておけば良い)もしrが前に何かしらの値で定義されていたのなら、 r = r + 1はHaskellではエラーメッセージを出す。 これは数学的文脈で明白に間違いである5 = 5 + 1と言うのに同類である。 (逆に技術の教科書には、命令型プログラミングのa = a + 1に慣れろと書いてあった) 変数の値がプログラム中変わらないので、変数はいかなる順序でも定義できる。例えば、以下のコードの断片は全く同じことをする y = x * 2 x = 3 x = 3 y = x * 2 物事を好きな順番で書いても良い、つまり、「xがyの前に宣言された」かその逆かを気にする必要はない。また、このことは一回しかものを宣言できないことの理由でもある。もし2回以上宣言できたとすると、上のコードが曖昧になってしまう。もちろんのことだが、それでもyを使うにはxの値が必要であるが、これは具体的な数値が必要になるまで重要でない。 今までの説明で、もしかしたら変数が変化しないHaskellで実際一体何が出来るのかと思っているかもしれない。しかし、見捨てないでくれ、この本の残りの部分で説明しようと思っていることだが、変数を一つも変更すること無くこの世のどんなプログラムも書けるようになる。 実際変数が変わらないお陰でかなり楽になる、というのもそれのお陰でプログラムの挙動がずっと一層予測しやすくなるからだ。これは純粋関数型プログラミングの重要な特徴である。 そして、そのことで命令型プログラミングのやり方や考え方とかなり違ったそれらが必要なのである。 関数 では、異なる半径の円の面積を計算したいとする。例えば、半径3の別の円の面積を計算してみよう。書いたばかりのプログラムから作るとすれば、rは既に5と定義されている。プログラム全体をr = 3と変更することが出来る。しかしすると、最初の円が計算できなくなる。代替策は新たな変数r2とr2で計算される面積のための変数area2を定義することだ。 この例が示すように、変数名には英字の他に数字含んで良い。(日本語はファイルからだとダメ、プロンプトからは可能)ただし、変数は小文字から始めなければならないが残りの部分については文字、数字、アンダースコア(_)、シングルクォート( )(と日本語がギリギリ)からなる任意の文字列を使うことが出来る(日本語には名前の1文字目の制約はない)。 2つの円を対象とした新しいソースファイルは以下のとおり r = 5 area = pi*r^2 r2 = 3 area2 = pi*r2^2 明らかなことだが、このやり方は円の面積公式を言葉通りに繰り返しているから不満足である。この頭使っていない繰り返しを無くすために一回だけ書いて異なる半径を適用させるのが好ましい。これがこそまさに関数のが出来ることである。 関数は引数値(パラメータともいう)を取り結果の値を与える(これは本質的に数学の関数と同じである)。Haskellでの関数の定義は単純である 変数を定義するように、ただし左辺に付ける関数の引数に気を払うこと。例えば、以下のコードはrと名前を付けた1引数に依る関数areaの定義である。 area r = pi * r^2 構文を注意深く見てみよう 関数名が最初に来て(上の例ではarea) 続いてスペースが一個そして引数(上の例ではr)とがある。 そして=の次に、関数の定義が既に定義した物々とともに筋通りに引数を使う公式がとしてある。 そして、関数の呼び出しごとに引数へ異なる値を入れることが出来る。コードをファイルに保存しGHCiに読み込ませて以下を試す *Main area 5 78.53981633974483 *Main area 3 28.274333882308138 *Main area 17 907.9202768874502 ゆえに、この関数を異なる半径で呼び出して、いかなる半径の円の面積も計算できる。 ここでの関数は数学的に以下のように定義される A(r) = \pi \cdot r^2 A(5) = 78.54やA(3) = 28.27のように数学では、パラメータは括弧によって囲まれる。しかし、Haskellのコードは括弧を付けても機能するが普通は省略される。Haskellは関数型言語なので、常に関数を使うことになる、なので可能である場合ならいつも余分な記号を最小にしたいのである。 また、括弧は式(値を与えるコード全てのこと)をともに評価させるためにまとめるのに使われる。以下の2つの式がいかに違う解釈をされるかに注意 5 * 3 + 2 -- 15 + 2 = 17 (乗算は加算の前になされる) 5 * (3 + 2) -- 5 * 5 = 25 (括弧のおかげ) area 5 * 3 -- (area 5) * 3 area (5 * 3) -- area 15 Haskellがどのように+や*と言った他のどの演算子よりも優先順序が先であるかに注意。これは例えば、数学で乗算が加算よりも先になされることと同じ流れである。 評価 GHCiに式を入力したときに厳密に何が起こるのかを理解してみよう。Enterキーを押した後、 GHCiは渡された式を評価をする。これはそれぞれの関数を定義に置き換え、一つの値になるまで計算をするということだ。例えば、area 5の評価は以下のように進行する。 area 5 = {左辺area rを右辺pi * r^2に変える} pi * 5^2 = {変数piを数値に変える} 3.141592653589793 * 5^2 = {べき乗(^)を適用} 3.141592653589793 * 25 = {乗算(*)を適用} 78.53981633974483 ここに示す通り、関数の適用や呼び出しというのは関数の定義の左辺を右辺に変えるということである。最後の工程として、GHCiは最終結果を画面に表示する。 関数を更に挙げてゆく double x = 2*x quadruple x = double (double x) square x = x*x half x = x / 2 (quadrupleは定義を見れば分かる通り4倍のこと) 演習問題 GHCiによってquadruple 5がどのように評価されるかを説明しなさい 引数の半分から12を引く(引いた結果を返す)関数を定義しなさい 複数のパラメータ もちろん、関数は2つ以上の引数を持つことも出来る。例えば、以下は幅と高さ(lengthとなっている)が与えられた長方形の面積を計算する関数である areaRect l w = l * w *Main areaRect 5 10 50 三角形の面積を計算する別の例 \left(A = \frac{bh}{2}\right)(底辺×高さ÷2で求める) areaTriangle b h = (b * h) / 2 *Main areaTriangle 3 9 13.5 例から分かる通り、複数の引数はスペース(全角半角は問わない)で分ける。これも 式をまとめるのに括弧を使わなければならないことがある理由である。例えば、値 xを4倍するのに以下のようには書けない quadruple x = double double x 理由はこの書き方はdoubleという名前の関数を2つの引数doubleとxに適用する意図となるからである、というのも関数は他の関数の引数になりうる(後々理由を説明する)。代わりの、引数の周りに括弧を付けなければならない blckquote quadruple x = double (double x) /blockquote 引数は常に与えられた順番通りに渡される。例えば subtract x y = x - y *Main subtract 10 5 5 *Main subtract 5 10 -5 ここの例ではsubtract 10 5は10 - 5に評価するが、 subtract 5 10は順番が違うので5 - 10に評価する。 演習問題 直方体の体積を求める関数を書きなさい 有名なギザのピラミッドに用いられた石の数をおおよそで求めなさい ヒント ピラミッドの体積と1ブロックの体積を見積もる必要がある。(Wikipediaに大きさが載っているが答えの石の数も書いてあるのが難点。また中に穴が開いているということ気にしなくて良い) 関数を組み合わせることについての意見 言わずもがな、加算(+)や乗算(*)といった予め定義された関数がが使えるのと同様に、新しい関数を定義するのに既に定義した関数を使うことができる。(Haskellでは演算子は関数として定義されている)例えば、正方形の面積を計算するために、 長方形の面積を計算する関数を再利用することが出来る areaRect l w = l * w areaSquare s = areaRect s s *Main areaSquare 5 25 そもそも、正方形は辺の長さが等しい長方形なだけである。 この原則はかなり単純に思えるかもしれないが、とても強力である。特に、数字の代わりに他のオブジェクトで計算し始めるときはそうである。 演習問題 円柱の体積を計算する関数を書きなさい。円柱の体積は円形である底面積(この章で既にこの関数は作った)に高さを掛けて求める。 ローカル定義 where節 関数を定義する際、関数にローカルな中間の結果を定義することはよくある。例えば、 3辺の長さa、b、cが与えられている三角形の面積を計算するヘロンの公式A = \sqrt{s(s-a)(s-b)(s-c)}を考える heron a b c = sqrt (s*(s-a)*(s-b)*(s-c)) □・・where □・・s = (a+b+c) / 2 変数sは三角形の周の長さの半分で平方根を求める関数sqrt の引数の中に4回書き出すのはただ長いだけで退屈である。 実は単に定義を順に書き連ねるだけではうまくいかない―― heron a b c = sqrt (s*(s-a)*(s-b)*(s-c)) -- sはここでは定義されていない s = (a+b+c) / 2 -- a,b,cはここで定義されていない ――なぜなら変数a、b、cは関数heronの右辺の中のみで利用可能であるが、ここに書かれているsの定義はheronの右辺の外であるからだ。この式を右辺の一部にするために、 whereキーワードを使う必要がある。 下に続く定義と区別するためにwhereとローカル定義がスペース4つでインデントされていることに注意。(スペースがうまく出力されないので □・・ と書いた。 入力の際にはスペースに変えること)以下はローカルとトップレベルの定義を併用した例である。(fig.1) areaTriangleTrig a b c = c * height / 2 --三角法を用いた方法 □・・where □・・cosa = (b^2 + c^2 - a^2) / (2*b*c) --余弦定理 □・・sina = sqrt (1 - cosa^2) --cos x ^2+sin x ^ 2 =1 □・・height = b*sina areaTriangleHeron a b c = result --ヘロンの公式を用いた方法 □・・where □・・result = sqrt (s*(s-a)*(s-b)*(s-c)) □・・s = (a+b+c)/2 スコープ さっきの例を注意深く見ると、変数名a、b、cを 2つの面積を計算する関数のそれぞれ1回ずつ、計2回ずつ使っていることに気づくだろう。 これが正しく動作する仕組みについて説明してゆく。 幸運にも、以下のコードの断片はは嬉しくない驚きは無い Prelude let r = 0 Prelude let area r = pi * r ^ 2 Prelude area 5 78.53981633974483 ここでの 嬉しくない驚き とはlet r = 0の定義が入り込んで、areaの結果 0を返すことである。これはrを2回目に定義したとき、1回目の rと違うrについて話題にしているからだ。これは実生活でも 起こることだ。あなたは、Johnという名前の人を何人知っているか?Johnという名前の人 に関して興味のあることは、殆どの場合、友達と John について話ができることであり、 文脈により、どのJohnを指しているのかが友達がわかることで、このことをスコープと呼ぶ。 スコープの専門的な裏側については説明しないつもりである(少なくとも今回は)。なので、 パラメータの値は関数の定義でどの変数を呼び出したかによらず厳格に関数を呼び出す時に渡した通りであるということを覚えておくだけでよい。 補足 上の例ではrは一番最後の定義に則るようにも見える。しかしこれは Prelude r を試すことで間違いであると判る。(0と帰ってくる)よって、この2つのr は別物である。 まとめ 変数は値を格納する。実際はHaskellの任意の式を格納する。 変数は変化しない。 関数は再利用するコードを書くのに役立つ。 関数は複数個パラメータを持つことも出来る。 そしてコメントはソースファイルの中のコードでない文章であることも学んだ 演習問題の解答 Haskell 次 真偽値型
https://w.atwiki.jp/paphi/pages/15.html
haskell random Haskellの乱数 乱数は疑似乱数に限定. import System.Random import Control.Monad.State 乱数の定義 乱数はseed値を与えると,値がランダムである無限リストを返す関数であるとひとまず定義する. 乱数の型を1から6までの整数とすると, inftyrand seed = [6, 5, 5, 3, ...] のようになる.ここで, inftyrand seed = x xs -- 先の例では, x = 6, xs = [5, 5, 3, ...] inftyrand seed == xs となるseed が存在すると仮定して,乱数を次のように定義することもできる. +seed の仮定について このseed はまず存在すると考えてよい. というよりは私の知る乱数は全て Seed - (a, Seed) という型で計算できる. 例えばC標準の線形randで連想されるアレが一番考えやすい.LCG, 線形合同法というらしい. http //en.wikipedia.org/wiki/Linear_congruential_generator 簡単に言うと,x = x * c + a (mod m).この乱数は next x = let y = x * c + a `mod` m in (y, y) と表すことができる.ここでSeedはただの整数値である. Seedをもう少し複雑にすれば,一気に生成するタイプにも対応できる.多分.(SFMTとか) Seedの一般化としてRandomGenがある...この辺から表現が曖昧に 複雑なSeed型からどうやって次の値を得るのか,ではなく, RandomGen型のinstanceであるgが next g - (Int, g) なる関数を持ち, そこから各種乱数値を生成している...と思う.未確認. いままで(というかLCGのみ?)値と考えてきたSeedを,次の乱数を生成できる状態と考えることによる一般化である. seed が存在するというより,Haskellの乱数は Seed - (a, Seed) 型の関数を主軸に構成されている,と表現したほうが正しいと思う. Stateを睨んだ乱数の定義 乱数はseed値を与えると,ランダム値一つと上記のseed で構成されるタプルを返す関数である. next Random a = Seed - (a, Seed) Random a は乱数によって生成できる型を表す. 乱数の計算を状態付き計算とみなすことが出来,その型は明らかにStateモナドである. newtype State s a = State (s - (a, s)) state (s - (a, s)) - State s a runState State s a - s - (a, s) evalState State s a - s - a evalState m s = fst (runState m s) nextのような関数からstateで値を作って,という形になるかと. System.Randomにある関数を使って,nextの例を一つ挙げておく. next = randomR (1, 6) まず後の定義から前の定義の乱数が生成しうることを示そう. State Seed 型がMonadのinstanceであるため,IO型の感覚でdo記法を扱えるし,Monadっぽい関数を使うこともできる. 例えばControl.Monadのsequence関数を使うと,inftyrandは次のように書ける. ついでにState型の使い方も併記.state被せないとMonadみたく扱えないはず...これで合ってるんだろうか? ir_state Random a = State Seed [a] ir_state = sequence . repeat $ state next inftyrand Random a = Seed - [a] inftyrand = evalState ir_state 無限リストを返す関数となる.Stateに限っては多分遅延評価につき安全. +do記法の例 do記法で書いてみる.極端な例ですまぬ. ir_state = do a1 - s a2 - s a3 - s a4 - s a5 - s a6 - s a7 - s a8 - s return [a1+a8, a2+a7, a3+a6, a4+a5] where s = state next IOとかで使ってみる 例として,この関数をIOにのせることを考える.System.Randomにお誂え向きの関数がある. getStdRandom (StdGen - (a, StdGen)) - IO a StdGen型は先ほどまでのSeed型と同じ役割を果たす. main = do ns - liftM (take 4) $ getStdRandom $ runState ir_state print ns ただ値1個だけとかならState経由せずにSystem.Randomの関数を直接使った方がいい. System.Random RandomGenの定義のせるけどこれ32bitと64bitで違ったりしないんだろうか.要調査. nextは説明済み,genRangeは範囲制限,splitって何だろう. class RandomGen g where next g - (Int, g) genRange g - (Int,Int) split g - (g, g) このStdGenは処理系標準の乱数という位置付け. data StdGen instance RandomGen StdGen mkStdGen Int - StdGen getStdRandom (StdGen - (a, StdGen)) - IO a getStdGen IO StdGen setStdGen StdGen - IO () newStdGen IO StdGen 処理系にStdGen型の値が1つあって,getStdGenはそれを直接,newStdGenはsplitを使って分岐させるイメージ. 実装見る限りLCGではない.何だろう. 型から推して知るべし.R=range.[a]は無限リスト. class Random a where randomR RandomGen g = (a,a) - g - (a,g) random RandomGen g = g - (a, g) randomRs RandomGen g = (a,a) - g - [a] randoms RandomGen g = g - [a] randomRIO (a,a) - IO a randomIO IO a IO [a]は無い.多分死ぬから. 注釈 State型の定義は本当はStateTを使ってるんだけどスルーしてる. StateTの中にももう一つMonadがあるんだけどそれはStateT内で完結すると考えて構わない.
https://w.atwiki.jp/kenichiro90/
Haskellとは? Haskellとは、純粋関数型プログラミング言語のことです。はっきりいって、詳しいことはほとんど分かりません。なので、Wikipediaなどで調べてください。適当ですみません... このページの方針 一応、このページではHaskellの解説や、まだまだ翻訳されていない英文のマニュアルなどの翻訳活動などを行うつもりです。正直一人ではつらいので、自由に翻訳・編集してください。お願いします。 Haskellの解説 英文ドキュメントの翻訳 リンク これから数を増やしていくつもりです。 Haskell-HaskellWiki Haskell-Wikipedia - -
https://w.atwiki.jp/hirokidaichi/pages/18.html
Haskell備忘録
https://w.atwiki.jp/kenichiro90/pages/16.html
この章では、Haskellでコードを書くために必要なプログラムのインストール方法を探ります。 Haskellのインストール Haskellで作業をするためには、コンパイラが必要です。コンパイラは、他の言語のようなもので、あなたの書いたコードを用いて、実行できるように実行可能ファイルを生成するプログラムです。 コンパイラにはいくつかの選択肢がありますが、最も一般的で、最も機能の多いものはGHCです。GHCは、Glasgow Haskell Compiler(これは、もともとグラスゴーの大学で書かれました)の略です。ほとんどすべてのシステムとアーキテクチャでGHCを利用することができます。それらには、Windows、Linux、そしてFreeBSDが含まれます。もし、パッケージ管理の機能を持ったLinuxスタイルのディストリビュージョン上で動かすならば、まず、パッケージマネージャでGHCを探してください。もし、パッケージマネージャで見つからない、もしくは、Microsoft Windows上で動かすならば、GHCのダウンロードページで探してください。 GHCをソースコードからコンパイルしたいと思っている人たちにとって、そのようなことをすることは最もよくない考えです。GHC自体がほとんどHaskellで書かれているので、ソースコードから自力でコンパイルするのは非常にトリッキーです。GHCのビルドガイドはありますが、実際バイナリファイルをダウンロードすることと比べると、そのすべての手順は非常に難しいものとなるでしょう。 インタラクティブモードを使う もし、GHCをインストールしたならば、GHCiというサイドラインプログラムもインストールしたでしょう。GHCiの i は、 interactive という意味で、実行してみればわかるでしょう。シェルを開き(もしくは、Windows上で起動するならば、スタートをクリックし、ファイル名を指定して実行、それから cmd とタイプし、Enterキーを押す)、ghciとタイプし、Enterキーを押してください。 そうすると、以下のようなものが出力されるはずです。 GHC Interactive, version 6.4.1, for Haskell 98. http //www.haskell.org/ghc/ Type ? for help. Loading package base-1.0 ... linking ... done. Prelude はじめの部分はGHCiのロゴです。これは、ベースパッケージを読み込んでいることを知らせるものです。そして、GHCにより読み出される組み込み関数とモジュールのほとんどにアクセスするでしょう。最後に、Prelude の部分はプロンプトとして知られているものです。この部分は、コマンドを入力し、GHCiがコマンドを評価したものを返す場所です。 いくつかの基本的な計算をして見ましょう。 Prelude 2 + 2 4 Prelude 5 * 4 + 3 23 Prelude 2 ^ 5 32 この演算子は、ほかのプログラミング言語で使われているものと似ています。例えば、+は加算、*は乗算、そして、^は指数を表します。 GHCiは非常に強力な開発環境です。このコースを通して上達すると、どのようにしてソースファイルをGHCiを読み込み、それらの異なったビットを評価するかということを学ぶでしょう。 次の章では、Haskellの基本的な概念のいくつかを紹介します。Haskellの基本的な概念の中に飛び込み、私たちにとってはじめてのHaskellの関数を見てみましょう。
https://w.atwiki.jp/hirotakaohkubo/pages/21.html
多少手間をかけて、Haskellコードをきれいに組版するためのスタイル。 GitHubで触れるようにしました。 https //github.com/gotoki-no-joe/haskell-style オリジナルは http //www.cse.unsw.edu.au/~chak/haskell/haskell-style/ にあるものです。 多少のコマンド追加と日本語マニュアルを付けました。 コメント 名前 コメント
https://w.atwiki.jp/mamonbo/pages/16.html
Haskell-logo.png このページはWikibooksのHaskellのページ(英語版)の日本語訳である。 なぜ日本語版に上げないのかというと、書き言葉で訳せる気がしないということと、 私自身がHaskell初心者でこれを書きながら学ぼうと思っているからである。 元がクリエイティブ・コモンズ 表示 - 継承 3.0(CC BY-SA 3.0)なので、これもCC BY-SA 3.0 となります。 Haskellは関数型言語である。もしプログラミングの経験があるのなら、 概要を見て、Haskellがどのように動くのかをいくらか見、他の言語とどう違うかを見てみよう。 Haskellは幾らかの点に置いて他と異なっている Haskellは純粋関数型言語である。もし同じ関数を同じ引数で2回違うところで呼び出すと、2回とも全く同じ値を返す。(参照透過性という) Haskellはtypeclassやgeneralized algebraic data typesと言った(それぞれ型クラス、一般代数データ型といったところか)洗練された特徴を持つモダンな型付けシステムを提供する。(このような用語はすぐに滑らかに口から出るようになる) Haskellは遅延型つまり最終的な結果を得るために必要なときだけ計算をする言語でもある。 (modernをカタカナで訳すのはコンピュータ界隈ではよくある話。対義語の古いって言ってもだいたい20世紀だったりするからかと) 純粋な関数だけを取り扱ってコードをずっと簡単に理解し、それぞれの関数の正しさを解析し、証明しさえするのが簡単になるからHaskellプログラマはHaskellを享受するのである。その上、先進的な型システムが馬鹿げた間違い、真面目な間違い両方を見つけるのを助けてくれる。 この本では、Haskellのとても初歩的なところから先の特徴までと、コンピュータプログラミング一般両方について紹介することを目標にしている。経験のあるプログラマにはこの工程に大いに辛抱強くいてもらいたい。絶対に、最も慣れ親しんだ言語はHaskellを大いに異なっていて、 君たちの言語からの習慣がHaskellの仕組みを理解するのの障壁になるかもしれない。仕組みは単純なのだが異なるのだ。離れていて数学的な関数型プログラマの頭を通して世界を見るための学習を重要なことを理解していかなる言語の境界を遥かに超えたところへもたらしてくれる、素晴らしい新しい世界での冒険として捉えてほしい。 概要 この本は初級編、中級編、より最近の問題を取り扱う実践編に分かれている。実践編ではほとんど初心者編で習ったことのみ使う。 (ここにページ作成に貢献するように説得する文章が書いてある) 本家ではプロンプトの場合は実線の枠、ソースファイルの場合は点線枠の囲いがあったが、@wikiでは点線枠が出せそうにないのでそれぞれ赤枠(行頭スペース)、青枠(blockquoteタグ)で代用している。 初級編 Haskell/変数と関数 Haskellの基本といくつかのよく使われるライブラリで単純なプログラムが作れるようになる。 ほとんどの章には理解度を調べるために役立つ演習問題がある。それぞれの章の最後に解答のリンクが貼ってあるので、知識の正確さを確かめたり、行き詰まった時に答えを知ることができるようになっている。 Haskellの基本 環境の構築 変数と関数 真偽値 型の基本その1 リストとタプル 型の基本その2 Next steps Building vocabulary 簡単な入出力 Haskell初級第一 Template Haskell chapter/Elementary Haskell Haskell初級第二 Template Haskell chapter/Intermediate Haskell モナド Template Haskell chapter/Monads 中級編 This section introduces wider functional programming concepts such as different data structures and type theory. It will also cover more practical topics like concurrency. Haskell中級 Template Haskell chapter/Advanced Haskell 型で遊ぶ Template Haskell chapter/Fun with Types Wider Theory Template Haskell chapter/Wider Theory Haskell Performance Template Haskell chapter/Haskell Performance Haskell in Practice Day-to-day issues of working with Haskell include items such as knowing the standard libraries, building graphical interfaces, and working with databases. You should be able to jump directly to this section from the beginner s track. Libraries Reference Template Haskell chapter/Libraries Reference General Practices Template Haskell chapter/General Practices Specialised Tasks Template Haskell chapter/Specialised Tasks Appendices /Syntactic sugar/ Answers to exercises Authors and Acknowledgements About the book /Notes for contributors/ /Style conventions/ /To do/ Templates for the Haskell wikibook Experimental Modules List of topics Other Haskell tutorials Haskell Meta-tutorial - the tutorial to find other tutorials Learn You a Haskell for Great Good - Tutorial aimed at beginners who may have experience in imperative programming languages but haven t programmed in a functional language before. Freely available online under a CC-BY-NC-SA license; also released as a conventional book. Real World Haskell - an O Reilly book, available online at no charge (CC-BY-NC license). Built around case studies of practical applications. Write Yourself a Scheme in 48 Hours - (imported here) An alternate approach to teaching Haskell (and perhaps Scheme), aimed at a more advanced audience (though not necessarily one that knows how to program!) Yet Another Haskell Tutorial - (imported here) is aimed at beginners and takes a practical approach to things. Additional resources haskell.org - Resources for learning Haskell. What I Wish I Knew When Learning Haskell - A wide-ranging collection of concise summaries of many intermediate and advanced Haskell topics. Released in the public domain. The resource page for the Haskell the craft of functional programming book. Template status
https://w.atwiki.jp/knenethaskell/pages/22.html
ここでは、haskellの動作ではなくて、プログラムの一般的なことを説明するよ。 リンクを貼っておいて、こう書くのも難だけど、ここを読むと理解が混乱するかも知れない。 一応、言語の根幹に関わることだから説明するけど、深く考えない方が良い気がするよ。 副作用(side effect)というのは、メッセージの表示や、変数への代入といった、状態が変化する作用のことを言うんだ。 そうでない作用をする関数を純関数というけど、用語の対応は良く分からない。 ともあれ、副作用は関数型言語を使っていると良く問題にされるんだ。 関数型言語ではない言語は、大抵副作用を持っている命令で構成されている。 変数に計算結果を代入して、それを表示する……のようにね。 でも、関数型言語はそうじゃない。 プログラムの大半は値の宣言で出来ている。 とりあえず、説明のためにCの関数(と呼ばれているもの)とhaskellの関数(と呼ばれているもの)を示そう。 //Cの関数 int fc(int x){return (x*x);} --haskellの関数 fh x = x*x このfcとfhは、それぞれの言語でほぼ同じように扱われる。けど、その意味合いは少し違う。 fcはxを与えたらx*xを返せ、と言う命令だ。この命令自体はintと同様に扱えることを明示している。 一方、fh xは値である。この宣言は、実はfh xに対するものなのだ。そう読むと、本当にそのままを表していることが分かる。 ちなみに、fhという関数そのものを宣言したいのであれば、まだ出てきてない表現だけど、 fh = \x - x と書くことになる。実質的には上の定義と同じになる。 要は、上の定義だと、fh xがx*xという値として宣言され、そこから推論された結果、fhはxを引数にx*xを返す関数だとされるのである。 で、型推論の結果、xに入る値は*が使える値、つまり数値に限定される。 見た目は似ているけど、意味は大分違う。もちろん、使われ方も違う。 Cの命令は、それ自体が副作用である。returnは、命令を呼び出した先に値を返すという動作を示す。 こういう書き方をしている都合上、他に副作用があるか、命令を使う側からすると判断が付かない。 一方、haskellの定義は単に、値に名前を付けているだけである。値だから、型さえ合っていれば好きに使って良いことが分かる。 値なんだから、副作用なんかあるわけがない。 ……そう、haskellは値の定義しかできないのだから、副作用なんか持たないのだ。 この重大な特長のために、純関数型言語と呼ばれている。 それは理解できたけど、なんか怪しい。 プログラミング言語なのだから、変数を使ったり動作をさせたり出来なくちゃおかしい。 実際に触って確かめたように、画面の表示も出来るわけだし(変数はまだ見てないけど)。 では、謎を解明するために、明らかに副作用を持つ、画面を表示するプログラムで考えてみよう。 //C:簡単のため、宣言は省略 int main(void){printf("Hello,world!");return 0;} --haskell main = putStrLn "Hello,world!" これをコンパイルすると、動作が同じプログラムが出来ると思う。haskellの方が容量は大きいけど(ぁ main関数を読んでない人は、それを参考にするか、フィーリングで理解してね。 Cは明らかに動作を記述している。mainが呼び出されると、printf命令が実行される。 これは明らかに値ではないよね。値がむき出しに書かれているというのはおかしい。 で、どこかに向かって0を返している。 私はCには詳しくないので良く分からないけど、関数の形をしているから必要なんだろう。 そして、問題のhaskellである。 実行結果はCと同じなんで、それだけでは何だかわからないから、GHCiで調べてみよう。 まあ、printで調べたのと同じ気がするけど。 *Main t main main IO () そう、mainはIO ()という値なんだ。IOは型の名前だ。型の名前がIOでも、値は値だから、これが何かをしているわけじゃない。 Cのreturn 0と同様、どこかにIO ()を投げているだけだ。 説明書を読むと、これは無視するものなんだろう。 どうも、このソースコードを見ていると、IO ()が評価されると、そのタイミングで評価器がアクションを返すようだ。 haskellは遅延評価だから、呼び出されたときに評価されるわけだし。 そのアクションに対して、haskellのコードは無関係でいられる。だから、副作用がないかのようにソースを書けるんだ。 Cとhaskellのプログラムの動きをまとめてみよう。 C システムがCのプログラムをコールする。 mainの命令を実行する。中身は次の通りである。printfを実行する。 値 0 を返す。 haskell システムがhaskellのプログラムをコールする。 mainの値を評価する。このとき、評価系がmainで評価された値に対して何らかのアクションを起こす。 mainの値 IO () を返す。 haskellの方は少し怪しいけど、確かに実質的にはCと同じだね。 先ほどCでは全て副作用だと書いたけれど、実質的に副作用を無視した書き方もできる。 haskellも、全く副作用がないけれども、実際は副作用があるかのように書かれる。 こうやって比較すると、haskellの方が変に見えて使いづらそうに思える。 でも、ソースコードを比較して欲しい。haskellの方が簡潔に書かれているよね。 動きは大体同じだと思えば、構造を見るにはhaskellの方が見通しが良いんだ。 さて、今はこれ以上突っ込んだ話が出来ないので、次は合流ポイントである入出力へ進んでね。
https://w.atwiki.jp/knenethaskell/pages/12.html
処理系はコンパイラと対話式のインタプリタがあるGHCをダウンロードすればよい。 エディタは付属していないので適当なものを使おう。 ちょっと使ってみよう。 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 ちょっとバージョンが古いけど……、まあこんな感じである。 ちなみに、画面はxyzzyのghci-modeを使ってコピーしている。 Prelude 4 + 5 9 計算をそのまま実行してくれる。 Prelude 9 / 3 3.0 Prelude 1 / 3 0.3333333333333333 割り算はこんな感じ。 Prelude "Welcome , haskell world!" "Welcome , haskell world!" 文字列。 関数はあとで調べよう。 GHCについてのリファレンスは「栄光のグラスゴーHaskellコンパイルシステム利用の手引き」についてを見てみる。 haskellの使い方はHoogleで調べる。 ここら辺はhaskellが分かってこないと理解できない内容が多いから、今は紹介だけにしておく。 次は基本的なソースを見てみよう。
https://w.atwiki.jp/it-note/pages/12.html
Real World Haskell