Мне нужна функция +++
, которая добавляет два математических вектора.
Я мог бы реализовать векторы как [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
просто отключит компонент 3D-вектора z
. Хотя это может иметь смысл (более вероятно, что он должен расширить 2D-вектор до [x, y, 0]
), для других функций я думаю, что это может быть проблематично, чтобы либо произойти молча. Проблема с подходом к кортежу заключается в том, что он ограничивает вектор тремя компонентами.
Интуитивно я бы подумал, что было бы более целесообразно представлять векторы как (x, y, z)
, так как математический вектор имеет фиксированное число компонентов, и на самом деле не имеет смысла сглаживать (дописывать) компонент вектору.
С другой стороны, хотя очень маловероятно, что мне понадобится что-то другое, кроме 3D-векторов, это не кажется правильным для ограничения этого.
Я предполагаю, что я хочу, это функции, которые принимают два списка одинаковой длины или лучше, функции, которые работают с кортежами произвольного размера.
Любые предложения с точки зрения практичности, масштабируемости, элегантности и т.д.