Haskell: Между списком и кортежем

Мне нужна функция +++, которая складывает два математических вектора.

Я мог бы реализовать векторы как [x, y, z]и использовать:

(+++) :: (Num a) => [a] -> [a] -> [a]
(+++) = zipWith (+)

И, таким образом, разместить любой n-мерный вектор (так что это будет работать для [x, y]тоже).

Или я мог бы реализовать векторы как (x, y, z)и использовать:

type Triple a = (a, a, a)

merge :: (a -> b -> c) -> Triple a -> Triple b -> Triple c
merge f (a, b, c) (x, y, z) = (f a x, f b y, f c z)

(+++) :: (Num a) => Triple a -> Triple a -> Triple a
(+++) = merge (+)

Конечно, это немного сложнее, но когда я реализую все остальные векторные функции, это не имеет значения ( 50 строк вместо 40).

Проблема со списком заключается в том, что я могу добавить 2D-вектор к 3D-вектору. В этом случае zipWithпросто отрезает компонент z3D-вектора. Хотя это может иметь смысл (более вероятно, что он должен расширять 2D-вектор до [x, y, 0]), для других функций, я думаю, может быть проблематично, чтобы это происходило молча. Проблема с кортежным подходом заключается в том, что он ограничивает вектор тремя компонентами.

Интуитивно я думаю, что имеет смысл представлять векторы как (x, y, z), так как математический вектор имеет фиксированное количество компонентов и на самом деле не имеет смысла чтобы добавить (подставить) компонент к вектору.

С другой стороны, хотя очень маловероятно, что мне понадобится что-либо, кроме 3D-векторов, ограничиваться этим кажется не совсем правильным.

Думаю, мне нужны функции, принимающие два списка одинаковой длины, или, что еще лучше, функции, работающие с кортежами произвольного размера.

Любые предложенияс точки зрения практичности, масштабируемости, элегантности и т. д.?

15
задан mk12 16 May 2012 в 21:25
поделиться