Я подумал, что попробую смоделировать численное интегрирование векторных величин разной размерности, и решил, что классы типов — это то, что нужно. Мне нужно было что-то, чтобы определить разницу между двумя значениями и масштабировать ее с помощью множителя (чтобы получить производную), а также иметь возможность использовать функцию расстояния.
Пока у меня есть:
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