Haskell 始めてみる(01)

The Haskell 98 Report: Introductionより。

Haskell プログラムの大雑把な構成

  1. Haskell プログラムは、モジュールの集まり
  2. モジュールは、宣言の集まり
  3. 宣言は、式の集まり

Haskell の名前は 6 種類

  1. 変数名 (値を表す。)
  2. 構築子名 (値を表す。大文字始まり)
  3. 型変数名 (型システムに関わる実体への参照。)
  4. 型構築子名 (型システムに関わる実体への参照。大文字始まり)
  5. 型クラス名 (型システムに関わる実体への参照。大文字始まり)
  6. モジュール名 (モジュールへの参照。大文字始まり)

A Gentle Introduction to Haskell: Values and Typesより。

式、値、型の定義など

明確な定義があるのかわからないが、それが必要かどうかもわからないので、適当にまとめ。

構文上の用語
計算上の答とみなす抽象的実態
直感的には型は値の集合と考えることができます。

計算はすべて、式を値にすることで行われます。

ふむ。これを評価の定義と思っていいのかな。
式が構文上の用語と定義されてるのが興味深い。ようするに、式って字面のことだと。

すべての値は型をもちます。

ということは、評価可能な式にも型があると思っていいはず。

式が値を表しているのと同様に、型の表現式型値(あるいは単に型)を表す構文上の用語です。

これも構文上の用語。型の表現式も字面に対する概念で、型そのものは、抽象的概念と。

数学っぽい言語だと思うけど、数学でも型の表現式と型の区別なんてほとんどやらないから、Haskell の方がより厳しくなってる。
型は集合だけど、ある集合そのもの(例えば整数の集合)と集合を表す記号(\mathbb{Z})の違いは、普通の数学では気にしないからね。基礎論とか論理学では多分キッチリやるんだろうけど。

型の表現式の例には、IntegerCharInteger->Integer、といったアトミックな型と、[Integer](Char,Integer) というような構造を持つ型が含まれます。

型には、アトミックなものと、構造を持つものがあると。

第一級の対象

ファーストクラスオブジェクトのことと理解。

第一級の対象
関数の引数、返り値にすることができて、データ構造の中に入れることができるもの*1

Haskell の値は全て「第一級の対象」です。
(中略)
一方、 Haskell の型は「第一級の対象」ではありません。

ふむ。

型付け(タイピング typing)

型付け
値とその型を結びつけること
        5 :: Integer
      'a' :: Char
\x -> x+1 :: Integer -> Integer

:: の左辺が値で、右辺が型。::で型付けを行っていると。

宣言と関数

完全な定義は後回し(多分書かない)で、必要な分だけ。
2 種類の宣言が例に挙がっている。

Haskell の関数は、ふつう一連の等式によって定義されます。

inc n = n+1

「ふつう」と「一連の」を見逃すところだった。複数の等式で定義する事もあるし、そうじゃない定義の仕方もあるということだろう。
関数定義に、型シグネチャ宣言を明示的にしてもよい(ということは、しなくてもいい)。

inc   :: Integer -> Integer
inc n  = n+1

シグネチャ宣言は、C ではプロトタイプ宣言に相当するのかな?
あと、型付けと見分けがつかないけど、型付けの一種と思っていい?

等式も宣言だという事に注意。

評価、簡約

学術的な目的で式e1が評価されて、あるいは「簡約」されて別の式あるいは値e2になることを示したいときには、

e1 => e2 

という表記を用います。たとえば、

inc (inc 3) => 5 

「学術的な目的」、「簡約」、「表記」が何に対するものかが良くわからなかったので、パス。
あ、簡約は、式を式に変えることか。

多相型

多相型
全ての型の上で全称修飾された型

型変数は暗黙に全称修飾されています。

(∀a)[a] は、全ての型aに対して、aのリストの型からなる型の族を表しています。

なるほど。すっきりした。
Just x[a]とか、自由変数 aが残っていて気持ち悪かった。暗黙の全称修飾があったのね。
型が集合だから、型の集まりである多相型は型の「族」というのも納得。
複数の型変数がある多相型は、型変数の数だけ全称があるはずだけど、順番は問題になるかな?多分ならない気がする。とりあえずそういうことにしておく。

リスト

流れから外れるけど、例に出ているので。

リストの型
[a](多相型!)

リスト処理関数

:
ようするにcons。型はa -> [a] -> [a]
head
ようするにcar。型は[a] -> a
tail
ようするにcdr。型は[a] -> [a]

><

*1:これでいいのかな?動的言語でのファーストクラスオブジェクトとはどこが違ってくるんだろう?