web-dev-qa-db-ja.com

Haskellまたは初心者向けの標準ML?

私は、離散構造の下位区分コースを教えます。テキストブック Discrete Structures、Logic、and Computability を選択しました。これには、関数型プログラミング言語での実装に役立つ例と概念が含まれているためです。 (私もそれは良い教科書だと思います。)

理解しやすいFP言語でDSコンセプトであり、学生が使用できるものが必要です。ほとんどの学生は1学期または2学期しかありませんせいぜいJavaでのプログラミングScheme、Erlang、Haskell、Ocaml、およびSMLを見てから、HaskellまたはStandard MLのいずれかに決着しました。どちらかでアクティブなプログラマーである人々の意見。

  • HaskellとSMLの両方には、再帰アルゴリズムの記述を簡単にするパターンマッチングがあります。
  • Haskellには、そのようなリストが数学的に表現される方法とうまく一致するニースリストの内包表記があります。
  • Haskellには遅延評価があります。リスト内包法を使用して無限リストを作成するのに最適です。
  • SMLには、関数を定義して使用できる真にインタラクティブなインタープリターがあります。 Haskellでは、関数は別のファイルで定義され、インタラクティブシェルで使用される前にコンパイルされる必要があります。
  • SMLは、関数の引数を明確に確認し、わかりやすい構文で型を返します。例:val foo = fn:int * int-> int。 Haskellの暗黙的なカレー構文はもう少し鈍いですが、完全に異質ではありません。たとえば、foo :: Int-> Int-> Int。
  • Haskellはデフォルトで任意精度の整数を使用します。 SML/NJの外部ライブラリです。また、SML/NJはデフォルトで出力を70文字に切り捨てます。
  • Haskellのラムダ構文は微妙です-単一のバックスラッシュを使用します。 SMLはより明示的です。ただし、このクラスでラムダが必要になるかどうかはわかりません。

基本的に、SMLとHaskellはほぼ同等です。 Haskellのリスト理解と無限リストが大好きなので、Haskellに傾倒します。しかし、Haskellのコンパクトな構文に含まれる膨大な数のシンボルが学生の問題を引き起こす可能性があることを心配しています。私がSOに関する他の投稿を読んで集めたものから、HaskellはFPから始める初心者にはお勧めできません。しかし、単純なアルゴリズムを試すだけで、本格的なアプリケーションを構築するつもりはありません。

どう思いますか?


編集:あなたの素晴らしい反応のいくつかを読んだら、私の箇条書きのいくつかを明確にする必要があります。

SMLでは、インタープリターで関数を定義することと外部ファイルで定義することの間に構文上の違いはありません。階乗関数を書きたいとしましょう。 Haskellでは、この定義をファイルに入れてGHCiにロードできます。

fac 0 = 1
fac n = n * fac (n-1)

私にとって、それは明確で簡潔で、本の数学的定義と一致しています。ただし、GHCiで関数を直接記述したい場合は、別の構文を使用する必要があります。

let fac 0 = 1; fac n = n * fac (n-1)

インタラクティブなインタープリターを使用する場合、教育の観点から、学生がファイルとコマンドラインの両方で同じコードを使用できると非常に便利です。

「関数の明示的な確認」とは、関数を定義するとすぐに、SMLが関数の名前、引数の型、および戻り値の型を伝えることを意味します。 Haskellでは、:typeコマンドを使用する必要があり、やや混乱したカレー表記法を取得します。

Haskellのもう1つのクールな点-これは有効な関数定義です。

fac 0 = 1
fac (n+1) = (n+1) * fac n

繰り返しますが、これは教科書で見つけられる定義と一致します。 SMLではできません!

75
Barry Brown

Haskellが大好きなのと同じように、離散数学とデータ構造のクラス(および他のほとんどの初心者クラス)にSMLを好む理由は次のとおりです。

  • Haskellプログラムの時間とスペースのコストは、専門家であっても予測が非常に困難です。 SMLは、マシンを吹き飛ばすためのはるかに限られた方法を提供します。

  • インタラクティブインタープリターの関数定義の構文は、ファイルで使用される構文とidenticalであるため、カットアンドペーストできます。

  • SMLでの演算子のオーバーロードは完全に偽ですが、それも簡単です。型クラスに入らずにHaskellでクラス全体を教えるのは難しいでしょう。

  • 学生はprintを使用してデバッグできます。 (ただし、コメンターが指摘しているように、Debug.Trace.traceを使用してHaskellでほぼ同じ効果を得ることができます。)

  • 無限のデータ構造は人々の心を吹き飛ばします。初心者の場合、refセルとサンクで完全なストリームタイプを定義しておくとよいでしょう。

    datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
                               | VALUE of 'a
    type 'a thunk = 'a thunk_contents ref
    val delay : (unit -> 'a) -> 'a thunk
    val force : 'a thunk -> 'a
    

    これはもはや魔法ではなく、ここからストリーム(無限リスト)に移動できます。

  • Pythonのようにレイアウトは単純ではなく、混乱を招く可能性があります。

HaskellにはEdgeがある2つの場所があります。

  • Haskellコアでは、定義の直前に関数の型シグネチャを書くことができます。これは、学生やその他の初心者にとって非常に役立ちます。 SMLで型シグネチャを処理する良い方法はありません。

  • Haskellには、より具体的な構文があります。 Haskell構文は、ML構文よりも大幅に改善されています。 MLプログラムで括弧をいつ使用するかについての短いメモ ;を書きました。これは少し役立ちます。

最後に、両方の方法をカットする剣があります。

  • Haskellのコードはデフォルトでは純粋なので、生徒が不純な構造(IOモナド、ステートモナド)に偶然出くわすことはほとんどありません。しかし、同じトークンでは、それらは印刷できません。I/ Oを行いたい場合は、最低でもdo表記法を説明する必要があり、returnは混乱を招きます。

関連トピックについては、コースの準備に関するいくつかのアドバイスがあります。見逃さないでください Purely Functional Data Structures by Chris Okasaki。生徒にそれを使わせなくても、必ずコピーを手に入れたいでしょう。

85
Norman Ramsey

私たちは、大学で最初の数年にHaskellを教えています。これについての私の気持ちは少し複雑です。一方で、Haskellを最初の数年に教えることは、彼らが命令的なスタイルを学ぶ必要がないことを意味します。 Haskellは、非常に簡潔なコードを生成することもできます。これにより、以前にJava.

学生がよく気づいたいくつかの問題:

  • パターンマッチングは、最初は少し難しい場合があります。学生は当初、値の構築とパターンマッチングがどのように関連しているかを見る際にいくつかの問題を抱えていました。また、抽象化を区別する際にいくつかの問題がありました。私たちの演習には、算術式を簡素化する関数の作成が含まれており、一部の学生は抽象的な表現の違いを見るのが困難でした(例:Const 1)およびメタ言語表現(1)。

    さらに、学生がリスト処理関数を自分で記述することになっている場合は、パターンの違いに注意してください

    []
    [x]
    (x:xs)
    [x:xs]
    

    途中でどれだけの関数型プログラミングを教えたいかに応じて、いくつかのライブラリ関数を与えて、それで遊んでもらうことができます。

  • 匿名関数については学生に教えませんでした。単にwhere句について教えました。一部のタスクでは、これは少し冗長ですが、それ以外の場合はうまく機能しました。また、部分的なアプリケーションについても伝えませんでした。これはおそらく、Haskellで説明するのは非常に簡単です(書体の形式のため)ので、それらに示す価値があるかもしれません。

  • 彼らはすぐにリスト内包表記を発見し、filtermapzipWithのような高階関数よりもそれらを優先しました。

  • タイプごとに考えを導く方法を教えるのを少し逃したと思います。ただし、これが初心者に役立つかどうかはわかりません。

  • 通常、エラーメッセージは初心者にはあまり役に立たないため、時々これらのヘルプが必要になる場合があります。私は自分で試したことはありませんが、主に優れたエラーメッセージを使用して、特に初心者を対象としたHaskellコンパイラがあります。 Helium

  • 小さなプログラムの場合、スペースリークの可能性などは問題になりませんでした。

全体的に、Haskellは良い教育言語ですが、いくつかの落とし穴があります。生徒が高階関数よりもリストの理解にはるかに慣れていることを考えると、これはあなたが必要とする議論かもしれません。コースの長さや、どの程度のプログラミングを教えたいかはわかりませんが、基本的な概念を教える時間を計画してください。

29
nominolo

ところで、

#SMLには、関数を定義および使用できる真にインタラクティブなインタープリターがあります。 Haskellでは、関数は別のファイルで定義され、インタラクティブシェルで使用される前にコンパイルされる必要があります。

不正確です。 GHCiを使用:

Prelude> let f x = x ^ 2
Prelude> f 7
49
Prelude> f 2
4

Haskell.org eduの教育には、Haskellの優れたリソースもあります。さまざまな教師の経験を含むページ。 http://haskell.org/haskellwiki/Haskell_in_education

最後に、Haskellを使用すると、楽しみのためだけにマルチコア並列処理を教えることができます:-)

13
Don Stewart

多くの大学がHaskellを最初の関数型言語または最初のプログラミング言語として教えているため、これが問題になるとは思いません。

そのようなコースでいくつかの指導を行った後、あなたが特定する可能性のある混乱がその可能性が高いことに同意しません。初期の混乱の原因として最も可能性が高いのは、不適切なレイアウトに起因する解析エラーと、数値リテラルが正しく使用されていない場合の型クラスに関する不思議なメッセージです。

HaskellはFPを始めたばかりの初心者にはお勧めできないという提案にも同意しません。突然変異を伴う厳密な言語がそうではないという点では、確かにビッグバンのアプローチですが、それは非常に有効なアプローチだと思います。

10
  • SMLには、関数を定義して使用できる真にインタラクティブなインタープリターがあります。 Haskellでは、関数は別のファイルで定義され、インタラクティブシェルで使用される前にコンパイルされる必要があります。

Hugsにはその制限がありますが、GHCiには次の機能はありません。

$ ghci
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> let hello name = "Hello, " ++ name
Prelude> hello "Barry"
"Hello, Barry"

HugsよりもGHC(i)の方が好きな理由はたくさんありますが、これはそのうちの1つにすぎません。

  • SMLは、関数の引数を明確に確認し、わかりやすい構文で型を返します。例:val foo = fn:int * int-> int。 Haskellの暗黙的なカレー構文はもう少し鈍いですが、完全に異質ではありません。たとえば、foo :: Int-> Int-> Int。

SMLには、「暗黙のカレー」構文と呼ばれるものもあります。

$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- fun add x y = x + y;
val add = fn : int -> int -> int

基本的に、SMLとHaskellはほぼ同等です。 Haskellのリスト理解と無限リストが大好きなので、Haskellに傾倒します。しかし、Haskellのコンパクトな構文に含まれる膨大な数のシンボルが学生の問題を引き起こす可能性があることを心配しています。私がSOに関する他の投稿を読んで集めたものから、HaskellはFPから始める初心者にはお勧めできません。しかし、単純なアルゴリズムを試すだけで、本格的なアプリケーションを構築するつもりはありません。

私はHaskellをSMLよりもずっと使いたいと思っていますが、私はまだSMLを最初に教えます。

  • Nominoloの考えを再確認すると、リストの内包表記doは、生徒が高階関数に到達するのを遅らせているようです。
  • 遅延と無限のリストが必要な場合は、明示的に実装することをお勧めします。
  • SMLは熱心に評価されているため、実行モデルは理解しやすく、「printfによるデバッグ」はHaskellよりもはるかに優れています。
  • SMLの型システムも簡単です。あなたのクラスはおそらくとにかくそれらを使用しないでしょうが、Haskellの型クラスはまだ克服するための余分なバンプです-'a''a SMLの区別は十分に厳しいです。
9
ephemient

ほとんどの答えは技術的なものでしたが、少なくともそうでないものを検討する必要があると思います:Haskell(OCaml)は、現時点では、より広いコンテキストでより大きなコミュニティを使用しています。 Hackage には、利益と楽しみのために書かれたライブラリとアプリケーションの大きなデータベースもあります。これは、コース終了後に一部の生徒が言語を使用し続け、後で他の関数型言語(標準MLなど)を試してみる上で重要な要因になる可能性があります。

7

OCamlとF#があなたの懸念の多くに対処していることを考えると、あなたはOCamlとF#を検討していないことに驚いています。学習者にとって、まともで有用な開発環境は最優先事項ですか?その点で、SMLはかなり遅れており、F#は他のすべてのFPLよりもずっと進んでいます。

また、OCamlとF#の両方にリストの内包表記があります。

4
Jon Harrop

ハスケル。 Haskellを使って学んだことにより、CSのアルゴリズム/理論のクラスで先を行っています。これは非常に包括的な言語であり、大量のCSを教えてくれます使用するだけでです。

ただし、SMLの学習ははるかに簡単です。 Haskellには、レイジー評価や制御構造などの機能があり、はるかに強力になりますが、学習曲線が急勾配になります。 SMLにはそのような曲線はありません。

とは言っても、Haskellのほとんどは、Ruby、ObjC、Pythonなどの科学的/数学的ではない言語から学習していないものでした。

2
Nate Symer