Elmのnumberについて

2023/10/21に公開

はじめに

この記事では Elm のnumber型について説明する。具体的には以下のように数値のタプルを宣言した時の( number, number1 )型について理解することを目的とする。

> (1, 2)
(1, 2) : ( number, number1 )

number 型とは

Elm では型の名前が大文字から始まるものは普通の型である。例えば、IntFloatStringなどがそれにあたる。一方で、型の名前が小文字から始まるものは型変数である。例えば、List aid : a -> aaが型変数にあたる。

number型は型の名前が小文字から始まるため、型変数に分類される。ただ、numberという型変数は Elm の言語仕様として定められた特殊な型変数で、number型はInt型かFloat型しか当てはめられない制約を持つ。Elm にはnumber以外にも、幾つか特殊な型変数が定められている[1]

はじめにの部分で触れた例には型変数numbernumber1が含まれている。Elm の場合、特殊な型変数の最後に数値を付け加えた型変数も特殊な型変数として扱われる[2]。そのためnumber1numberとは別の変数として扱われる。したがって( number, number1 )型は(Int, Int)型や(Float, Float)型に加えて、( Int, Float )型や( Float, Int )型などに当てはめることができる。一方で(number, number)型とした場合は、二つの型変数が同じであるため、(Int, Int)型や(Float, Float)型しか当てはめることができない。

例をで説明する。

はじめに(number, number)を用いた例を示す。

> func: ( number, number ) -> number
| func ( a, b ) = a + 11

> x : (Int, Int)
| x = (1, 2)

> func x
12 : Int

> y : (Int, Float)
| y = (1, 2.0)

> func y
This `y` value is a:

    ( Int, Float )

But `func` needs the 1st argument to be:

    ( Int, Int )

この場合、func関数の引数のペアの型は一致する必要があるため、(Int, Float)型の変数yを引数に渡すことができない。

次に(number, number1)を用いた例を示す。

> func: ( number, number1 ) -> number
| func ( a, b ) = a + 11

> x : (Int, Int)
| x = (1, 2)

> func x
12 : Int

> y : (Int, Float)
| y = (1, 2.0)

> func y
12 : Int

この場合、func関数の引数のペアの型は一致する必要がないため、(Int, Float)型の変数yを引数に渡すことができる。

おわりに

この記事では Elm のnumber型について説明した。Elm には型クラスはないが、言語仕様によって定められた特殊な型変数がある。これによって、型クラスに似たことを実現している。

ただ、ユーザーに対して制限された型変数の拡張を許していないため、例えば有理数型Ratioを定義作成したとしても、それを型変数 number に付け加えることができない。またmapが定義された型変数をfunctorとして新たに定義して、ListMaybeResultなどをそれに加えることもできない。この辺りは、言語をシンプルに保つためにあえて対応しない決定をしたんだと思う。

個人的には型クラスって難しいし、Elm 本来の Web UI の状態管理を簡単に行うという用途であれば、制限された型変数があるだけで十分だと思う。

脚注
  1. https://guide.elm-lang.org/types/reading_types.html ↩︎

  2. https://elmprogramming.com/type-system.html#tuple-type ↩︎

Discussion