Elmのnumberについて
はじめに
この記事では Elm のnumber
型について説明する。具体的には以下のように数値のタプルを宣言した時の( number, number1 )
型について理解することを目的とする。
> (1, 2)
(1, 2) : ( number, number1 )
number
型とは
Elm では型の名前が大文字から始まるものは普通の型である。例えば、Int
やFloat
やString
などがそれにあたる。一方で、型の名前が小文字から始まるものは型変数である。例えば、List a
やid : a -> a
のa
が型変数にあたる。
number
型は型の名前が小文字から始まるため、型変数に分類される。ただ、number
という型変数は Elm の言語仕様として定められた特殊な型変数で、number
型はInt
型かFloat
型しか当てはめられない制約を持つ。Elm にはnumber
以外にも、幾つか特殊な型変数が定められている[1]。
はじめにの部分で触れた例には型変数number
とnumber1
が含まれている。Elm の場合、特殊な型変数の最後に数値を付け加えた型変数も特殊な型変数として扱われる[2]。そのためnumber1
はnumber
とは別の変数として扱われる。したがって( 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
として新たに定義して、List
やMaybe
やResult
などをそれに加えることもできない。この辺りは、言語をシンプルに保つためにあえて対応しない決定をしたんだと思う。
個人的には型クラスって難しいし、Elm 本来の Web UI の状態管理を簡単に行うという用途であれば、制限された型変数があるだけで十分だと思う。
Discussion