プログラムは、動かす前に間違いを教えてくれる?
表計算ソフトで名前と数を足すと、おかしな答えが出て、気づくのはあとになります。Haskell では、それぞれの関数が受け取るものと返すものの種類を書いておき、何かを動かす前にそれを確かめます。すると、ある種類の間違いはそもそも起こりません。
このレッスンの終わりに
メモ
Haskell の関数を読んで実行し、その型から分かることを言える。
キーワード
- 関数:値を受け取って値を返すもの。
- 型:値の種類。整数なら
Int、文字ならString。 - 型シグネチャ:関数に型を与える行。たとえば
square :: Int -> Int。 - リスト:同じ型の値を順に並べたもの。
[1, 2, 3]と書く。 - 畳み込み(fold):リストの全部の要素をひとつの値にまとめる方法。
はじめに:もう知っていること
メモ
頭の中で答えましょう。1. 数学で f(x) = x * x のとき、f(5) はいくつ? 2. 7 と "seven" は同じ種類のもの? 3. リスト 1, 2, 3 の合計は? 答え: 25。違う。片方は数で、もう片方は文字。6。
始める前に
メモ
レッスンの上のバーにある ラボを開始 を押し、動いていると表示されるまで待ちます。コンテナはひとつ、haskell です。ブラウザーで開く画面はないので、ターミナルを使います。docker exec haskell は、その中でコマンドをひとつ実行する命令です。コンパイラーは毎回、起動に数秒かかります。表示されるものはすべて英語で、このページの言語には関係ありません。下の 実行 ボタンは、それぞれのコマンドをラボのターミナルに、同じセッションの中で順番に入力します。様子を見たいときや自分で入力したいときは、バーの ターミナルを開く(新しいタブ) を押します。
関数には型シグネチャがある
このコマンドは最初のファイルを表示します。square :: Int -> Int の行が型シグネチャです。「square は Int を受け取り、Int を返す」と読みます。次の行がやり方で、square n = n * n です。ここでは関数に副作用はありません。同じ値を渡せば、同じ答えが返ります。-- はコメントの始まりです。
docker exec haskell cat Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ファイルを実行する、関数をたずねる
runghc はファイルを実行します。その main は 3 行、Hello, Haskell!、49、(True,False) を表示します。ghc -e は、ファイルを読み込んだ状態で式をひとつ計算します。最初は square の型をたずねて square :: Int -> Int と表示し、2 つめは呼び出して 144 と表示します。
docker exec haskell runghc Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
docker exec haskell ghc -e ":type square" Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
docker exec haskell ghc -e "square 12" Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
確認
ヒント
コードを読む前に、isEven :: Int -> Bool から何が分かる? 答え: 整数を受け取り、True か False を返す。
リストは関数で扱う
map は関数をすべての要素に当てはめ、filter はテストに通る要素だけを残します。最初のコマンドは 1 から 5 を square で 2 乗して sum で足し、55 を表示します。2 つめは 1 から 10 の偶数を残し、[2,4,6,8,10] と表示します。どちらも元のリストは変えず、新しい値を返します。
docker exec haskell ghc -e "sum (map square [1 .. 5])" Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
docker exec haskell ghc -e "filter even [1 .. 10]"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
関数は自分自身を呼べる。畳み込みはそれを代わりにやってくれる
Fold.hs の mySum は、最初の要素と残りの合計を足すことでリストを足し、空のリストで止まります。このコマンドは 6 を表示します。2 つめは、リストをひとつの値に畳み込む組み込みの foldr で同じことをして、1 から 100 の合計 5050 を表示します。
docker exec haskell ghc -e "mySum [1, 2, 3]" Fold.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
docker exec haskell ghc -e "foldr (+) 0 [1 .. 100]"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コンパイラーは型を確かめる
このコマンドは、square に数ではなく文字を渡します。何も実行されません。コンパイラーは <interactive> で始まるエラーを表示し、文字である [Char] 型と Int 型が合わないと言います。エラーは上から読みましょう。式のどこが間違いかが書いてあります。角かっこの中のコードや体裁は、バージョンによって変わることがあります。
docker exec haskell ghc -e "square \"two\"" Basics.hsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある思い込み
注意
型シグネチャは読む人のためのコメントにすぎない、と思われがちです。そうではありません。コンパイラーはすべてを確かめ、コードが合わなければ何も実行されません。できるなら先にシグネチャを書きましょう。何をしたかったかを表し、コードが別のことを言っていればコンパイラーが教えてくれます。
最後の確認
ヒント
見返さずに答えましょう。1. Int -> Bool はどういう意味? 2. filter even [1 .. 10] は何を返す? 3. コンパイラーが型のエラーを見つけるのは、実行の前? 後? 4. 畳み込みはリストに何をする? 答え: 整数を受け取って True か False を返す。[2,4,6,8,10]。前なので、何も実行されない。全部の要素をひとつの値にまとめる。
先生へ
ヒント
このレッスンは、ラボの中で進めるレッスンの小さな見本です。手順と実行ボタンがレッスンで、ラボは生徒ひとりひとりのコピーです。ラボは GHC コンパイラーと 4 つの小さなファイルを入れたコンテナがひとつで、自動採点はありません。生徒は、試した式とそれぞれの表示、自分で書いた関数とその型とそれが働くことを示す呼び出し、型シグネチャが読む人に何を伝えるかについての一文を提出します。要点:1. 関数は値を受け取って値を返す。2. 型シグネチャは関数が受け取るものと返すものを表す。3. リストは map や filter などの関数で扱う。4. 関数は自分自身を呼べて、畳み込みは同じ仕事をする。5. コンパイラーは何かを実行する前に型を確かめる。よくある思い込み:シグネチャをコメントだと思うこと。準備:ラボとそのターミナル。ヒント:本体を書く前に関数の型を書かせましょう。答えは毎回同じで正確です。起動後の最初のコマンドは数秒かかります。名前とメッセージは英語で、ページの言語には関係ありません。