52700.fb2
:: v
(^+^)
:: v -> v -> v
negateV :: v -> v
class AdditiveGroup v => VectorSpace v where
type Scalar v
:: *
(*^)
:: Scalar v -> v -> v
Линейное пространство это математическая структура, объектами которой являются вектора и скаля-
ры. Для векторов определена операция сложения, а для скаляров операции сложения и умножения. Кроме
того определена операция умножения вектора на скаляр. При этом должны выполнятся определённые свой-
ства. Мы не будем подробно на них останавливаться, вкратце заметим, что эти свойства говорят о том, что
мы действительно пользуемся операциями сложения и умножения. В классе VectorSpace мы видим новую
конструкцию, объявление типа. Мы говорим, что есть производный тип, который следует из v. Далее через
двойное двоеточие мы указываем его вид. В данном случае это простой тип без параметров.
Вид (kind) это тип типа. Простой тип без параметра обозначается звёздочкой. Тип с параметром обозна-
чается как функция * -> *. Если бы тип принимал два параметра, то он обозначался бы * -> * -> *. Также
параметры могут быть не простыми типами а типами с параметрами, например тип, который обозначает
композицию типов:
newtype O f g a = O { unO :: f (g a) }
имеет вид (* -> *) -> (* -> *) -> * -> *.
Определим класс векторов на двумерной сетке и сделаем его экземпляром класса VectorSpace. Для нача-
ла создадим новый модуль с активным расширением TypeFamilies и запишем в него классы для линейного
пространства
{-# Language TypeFamilies #-}
module Point2D where
class AdditiveGroup v where
...
Теперь определим новый тип:
data V2 = V2 Int Int
deriving (Show, Eq)
Сделаем его экземпляром класса AdditiveGroup:
instance AdditiveGroup V2 where
zeroV
= V2 0 0
(V2 x y)
^+^ (V2 x’ y’)
= V2 (x+x’) (y+y’)
negateV (V2 x y)
= V2 (-x) (-y)
Мы складываем и вычитаем значения в каждом из элементов кортежа. Нейтральным элементом от-
носительно сложения будет кортеж, состоящий из двух нулей. Теперь определим экземпляр для класса
VectorSpace. Поскольку кортеж состоит из двух целых чисел, скаляр также будет целым числом:
instance VectorSpace V2 where
type Scalar V2 = Int
s *^ (V2 x y) = V2 (s*x) (s*y)
Попробуем вычислить что-нибудь в интерпретаторе:
258 | Глава 17: Дополнительные возможности