top page > computer > haskell > web_lecture > for_programmer > typeclass_num.html
更新日:
文責: 重城良国

型クラス: Num

(工事中 60%)

はじめに

数というものは見た目ほど単純ではない。Haskellでは「数」というものの性質の複雑さを反映して数を扱う関数はさまざまな型クラスにわかれている。

加算、減算、乗算は型クラスNumのクラス関数となっている。しかし、除算は「整数」と「分数(小数)」とでは意味が異なる。よって別々の型クラスIntegralとFractionalとにわかれている。

また「数」には大小がある。と普通は思う。しかし複素数という「数」には大小がない。よって型クラスOrdを継承する型クラスRealは型クラスNumとはわけられている。

「分数(小数)」のなかでも「浮動小数点数」については三角関数、対数関数、指数関数などが定義できる。これは「整数の比」で表された「分数」では定義することが困難だ。そのため型クラスFloatingも別に作られている。

このようにさまざまな種類の「数」に対して定義できる演算と定義できない演算とを細かくわけるためにHaskellでは「数」に関する型クラスがいくつもある。ここでは基本となる型クラスNumについてだけ見ていこう。

型クラスNum

型クラスNumは以下のように定義されている。

class Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a

x - y = x + negate y
negate x = 0 - x

加算、減算、乗算が定義される。関数negateは正負を反転する。関数absは絶対値を返す。関数signumは値の符号を返す。正なら1を負なら-1を0なら0を返す。関数fromIntegerはIntegerからの変換関数だ。これによって整数リテラルがそれぞれの数値に変換される。

% ghci
Prelude> :t 18
18 :: Num a => a

整数リテラルは多相的だ。18のように書くと型クラスNumのインスタンスである型の値となる。

誤差の範囲

range.hs

誤差つきの計算の例を見ていこう。まずは誤差のある値の型を作成する。

data Range = Range Double Double deriving Show

誤差の範囲を最小値と最大値とで表現している。型Rangeを型クラスNumのインスタンスにする。

instance Num Range where

足し算は最小値と最大値とをそれぞれ足し合わせればいい。

Range a b + Range c d = Range (a + c) (b + d)

かけ算は最小値と最大値の4通りのくみあわせのなかから最小と最大をとりだす。

Range a b * Range c d = Range (minimum f) (maximum f)
where f = [a * c, a * d, b * c, b * d]

関数negateでは最大値と最小値とがいれかわる。

negate (Range a b) = Range (- b) (- a)

絶対値は範囲が0をまたぐときは最小値が0となる。

abs (Range a b)
| b < 0 = Range (- b) (- a)
| a < 0 = Range 0 (max (- a) b)
| otherwise = Range a b

関数signumは最小値、最大値のそれぞれのsignumとした。

signum (Range a b) = Range (signum a) (signum b)

整数値からは誤差0.5の値として変換する。

fromInteger n = Range (fromInteger n - 0.5) Range (fromInteger n + 0.5)

これで型Rangeを型クラスNumのインスタンスとすることができた。試してみよう。

% ghci range.hs
*Main> (35 + 23 - 50) * 8 :: Range
Range 48.75 80.75

まとめ

数値に関する型クラスはいくつかにわかれている。そのうちのもっとも基本的な型クラスNumについて学んだ。型クラスNumのインスタンスにすると加算、減算、乗算ができるほか、整数リテラルによってリテラル表記が可能となる。

「構文: deriving」へもどる 「種類(kind)とは」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics