Я подумал, что попробую смоделировать численное интегрирование векторных величин разной размерности, и решил, что классы типов — это то, что нужно. Мне нужно было что-то, чтобы определить разницу между двумя значениями и масштабировать ее с помощью множителя (чтобы получить производную), а также иметь возможность использовать функцию расстояния.
Пока у меня есть:
class Integratable a where
difference :: a -> a -> a
scale :: Num b => a -> b -> a
distance :: Num b => a -> a -> b
data Num a => Vector a = Vector1D a | Vector2D a a
instance Num a => Integratable (Vector a) where
difference (Vector1D x1) (Vector1D x2) = Vector1D (x1 - x2)
scale (Vector1D x) m = Vector1D (x * m)
distance (Vector1D x1) (Vector1D x2) = x1 - x2
difference (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
scale (Vector2D x y) m = Vector2D (x * m) (y * m)
distance (Vector2D x1 y1) (Vector2D x2 y2) = sqrt((x1-x2)*(x1-x2)
+ (y1-y2)*(y1-y2))
К сожалению, здесь есть пара проблем, которые я не понял, как решить. Во-первых, функция scale выдает ошибки. GHC не может сказать, что m и x совместимы, так как жесткое ограничение типа Num дано в экземпляре в одном случае, а в типе Vector в другом случае... Есть ли способ указать, что x и m являются того же типа?
(На самом деле я понимаю, что даже если x и m оба являются Num, они могут не быть одним и тем же Num. Как я могу указать это? Если я не могу понять это с Num, использование Double приведет к хорошо, но я предпочитаю держать это в общих чертах.)
Аналогичная проблема с distance. Попытка указать тип возвращаемого значения Num не удалась, так как в определении экземпляра нельзя сказать, что a будет содержать значения, совместимые с b.
Vector2D (a,a), но используете его так, как если бы он был определенVector2D a a; точно так же вы используетеVector1Dв нескольких местах, где вы, кажется, имеете в видуVector2D. - person dave4420   schedule 22.12.2009scale. - person Steve   schedule 22.12.2009