Haskell ラボ:関数と型で学ぶ関数型プログラミングをブラウザーで
このラボでは、生徒ひとりひとりに専用の Haskell コンパイラーと、読んで、実行して、変えられる 4 つの小さなファイルが用意されます。関数と型、リスト、畳み込みと再帰、そして自分で作る型です。Haskell のプログラムは、値を受け取って値を返す関数でできていて、どの関数にも、何かが実行される前にコンパイラーが確かめる型があります。
攻撃のラボではありません。どのコピーも、インターネットにも他の生徒にも通じる道がないので、何かをダウンロードすることも、中のものが誰かに届くこともありません。あるのはコンパイラーと、それに付いてくるライブラリーだけです。追加のパッケージは入れられないので、cabal install も stack もありません。
生徒が学ぶこと
プログラムは関数から組み立てられること、そして型がそれぞれの関数が受け取るものと返すものを表すこと。生徒は型シグネチャを読み、ファイルを実行し、式をひとつ計算し、リストに map と filter を当てはめ、自分自身を呼ぶ関数を書いて畳み込みが同じ仕事をするのを見て、実行の前にプログラムを止める型のエラーに出会います。4 つめのファイルでは、2 つの形をもつ自分の型と、どの形かで場合分けして分解する関数を扱います。プログラミングのパラダイムの入門に向いています。正確な文言は各自の試験団体の単元で確認してください。ここでは何も引用していません。
ブラウザーで動かす
ラボは、公式の haskell イメージから haskell というサービスをひとつ、権限のないアカウントで起動します。ウェブページはないので、ラボのバーの「ブラウザーで開く」の下にリンクはなく、コードの実行にはターミナルを使います。コンパイラーには docker exec haskell に続けて、ファイルを実行するなら runghc とファイル名、式をひとつ計算するなら ghc -e と引用符で囲んだ式を入力して届きます。コンパイラーは毎回、起動に数秒かかります。答えは毎回同じで、表示されるものはすべて英語です。ページの言語には関係ありません。
コンパイラーと対話するには、「ターミナルを開く」を押して docker exec -it haskell ghci Lists.hs と入力します。ghci> のプロンプトで式を入力して Enter を押します。たとえば map (* 2) [1, 2, 3] は [2,4,6] を表示します。:t に名前を続けると型が分かり、:quit で終わります。
- コンテナーのページを開く. バーの「つくる」を開き、「コンテナーを実行」を選びます。ページは誰でも開けて、Git ラボと SQL ラボはアカウントなしで起動できます。ほかのラボには無料アカウントが必要です。アカウントを作成してサインインし、「起動」を押します。
- ラボを探す. 「サンプルラボ」のカードにすべてのサンプルが並んでいます。Haskell:関数、型、リストを探します。
- 「起動」を押す. 「起動」はそのまま1回の操作で実行します。「先にファイルを編集」は compose ファイルを開くので、起動する前に変更できます。
- 開く. 開くウェブページはありません。ラボのページで「ターミナルを開く」を押し、docker exec haskell runghc Basics.hs と入力して最初のファイルを実行すると、Hello, Haskell!、49、(True,False) の順に表示されます。
生徒に提出させるもの
試した式とそれぞれの表示:ファイルの関数を呼ぶ式、リストに map か filter を使う式、コンパイラーに型のエラーを報告させる式。そのうえで、Basics.hs に足した自分の関数と、その型シグネチャ、それが働くことを示す呼び出し、型シグネチャが読む人に何を伝えるかについて自分の言葉で一、二文。自動採点はありません。関数と文章で理解が分かります。さらに進めるなら、先にシグネチャを書き、それが何を約束しているかを言わせてください。
このラボで進める基本のレッスン
Haskell Basics は、このラボの中で進める小さなレッスンです。関数とその型を読み、ファイルを実行し、リストに関数を当てはめ、リストを畳み込み、型のエラーに出会います。
無料の個人アカウントでは、ホームにある Basics モジュールで使え、どの学校もライブラリの Basics フォルダーからコピーできます。わざと小さくしてあります。ラボで進めるレッスンとは何かを先生に見せるためで、あとはラボが担います。変えたいときは、自分のモジュールにコピーしてください。
GitHub のコード
compose ファイルには Dockerfile がありません。公式の公開イメージ Haskell(GHC 入り)をバージョン 9.10.1 に固定し、権限のないアカウントで、メモリ 384 MB で動かします。GHC はメモリをよく使います。ファイルの実行、式ひとつ、対話プロンプト、こうしたファイルの完全なコンパイルでは、コンパイラー自身のファイルのキャッシュを含めて 250 MB 近くになり、同じ作業が 192 MB の中でも終わったので、384 MB なら余裕があります。イメージとコンパイラーは寛容なオープンソースライセンスで、当社は配布していません。ファイルは最初の起動時に 4 つの小さな練習ファイルを書き、ボリュームに保存するので、生徒が変えたものは停止して再開したあとも残ります。限界も正直に述べます。外へ出る道がないので追加のパッケージはなく、とても大きなプログラムはラボのメモリでは足りないことがあります。
課題として出す
課題の中で、何を提出するかを書いてください。
- ラボを作る. モジュールで課題を追加し、「コンテナーラボ」のカードを選んでから「GitHub リポジトリ」を選びます。https://github.com/mitsurutech/lab-haskell-lab とブランチ main を指定します。compose ファイルは既定の compose.yaml です。変更したい場合は、たとえば最初のファイルに関数を増やしたいときは、先にリポジトリをフォークしてください。
- 公開して試す. 「公開」すると、確認したコミットに固定されるので、あとでリポジトリを変更しても、すでに出したラボは変わりません。まず自分のコピーを起動してください。
- 配布する. ほかの課題と同じように配布します。期限を付けることもでき、課題には何をするか、何を提出するかを書いておきます。
- 提出物を採点する. 生徒のコピーを開いて提出された内容を確認し、採点します。足りない場合は理由を書いて差し戻します。
このラボを試す、そして費用
無料の個人アカウントで、このラボの基本レッスンに取り組めます。毎月、ほとんどのレッスンに足りる無料クレジットがあり、カードは要りません。クラスで使う場合、学校は最初の365日間、生徒50人まで無料で、その後は生徒1人あたりの年額です。すべてのラボが含まれ、教職員は無料です。
よくある質問
- 最初のコマンドが遅いのはなぜ?
- コンパイラーは毎回、起動してライブラリーを読み込む必要があり、それに数秒かかります。runghc でファイルを、ghc -e で式を実行すると、そのたびに起こります。続けて何度も試すなら、一度だけ起動する対話プロンプトの ghci を使ってください。
- 他の言語のページでも、名前やメッセージが英語のままなのはなぜ?
- ファイルのあいさつ、Just と Nothing という語、コンパイラーのすべてのメッセージは英語で、ラボはそれを変えません。レッスンがそのことを述べ、各答えをページの言語で説明します。
- 生徒はパッケージをインストールできる?
- できません。ラボにはインターネットへ出る道がないので何もダウンロードできず、コンパイラーに付いてくるライブラリーだけがあります。Data.Char など、それらのライブラリーにあるものは import できます。