Векторы судьбы

We use cookies. Read the Privacy and Cookie Policy

Давайте реализуем трёхмерный вектор и несколько операций для него. Мы будем использовать параметризованный тип, потому что хоть вектор и содержит только числовые параметры, он должен поддерживать разные типы чисел.

data Vector a = Vector a a a deriving (Show)

vplus :: (Num a) => Vector a –> Vector a –> Vector a

(Vector i j k) `vplus` (Vector l m n) = Vector (i+l) (j+m) (k+n)

scalarProd :: (Num a) => Vector a –> Vector a –> a

(Vector i j k) `scalarProd` (Vector l m n) = i*l + j*m + k*n

vmult :: (Num a) => Vector a –> a –> Vector a

(Vector i j k) `vmult` m = Vector (i*m) (j*m) (k*m)

Функция vplus складывает два вектора путём сложения соответствующих координат. Функция scalarProd используется для вычисления скалярного произведения двух векторов, функция vmult – для умножения вектора на константу.

Эти функции могут работать с типами Vector Int, Vector Integer, Vector Float и другими, до тех пор пока тип-параметр a из определения Vector a принадлежит классу типов Num. По типам функций можно заметить, что они работают только с векторами одного типа, и все координаты вектора также должны иметь одинаковый тип. Обратите внимание на то, что мы не поместили ограничение класса Num в декларацию типа данных, так как нам всё равно бы пришлось повторять его в функциях.

Ещё раз повторю: очень важно понимать разницу между конструкторами типов и данных. При декларации типа данных часть объявления до знака = представляет собой конструктор типа, а часть объявления после этого знака – конструктор данных (возможны несколько конструкторов, разделённых символом |). Попытка дать функции тип Vector a a a -> Vector a a a -> a будет неудачной, потому что мы должны помещать типы в декларацию типа, и конструктор типа для вектора принимает только один параметр, в то время как конструктор данных принимает три. Давайте поупражняемся с нашими векторами:

ghci> Vector 3 5 8 `vplus` Vector 9 2 8

Vector 12 7 16

ghci> Vector 3 5 8 `vplus` Vector 9 2 8 `vplus` Vector 0 2 3

Vector 12 9 19

ghci> Vector 3 9 7 `vmult` 10

Vector 30 90 70

ghci> Vector 4 9 5 `scalarProd` Vector 9.0 2.0 4.0

74.0

ghci> Vector 2 9 3 `vmult` (Vector 4 9 5 `scalarProd`

Vector 9 2 4) Vector 148 666 222