Как справиться с ограничением класса типов в функции-члене класса

GHCI жалуется на типы k и a внутри (k * a, k * b). Я предполагаю, что он не знает, что k является Num, но я не знаю, как это указать.

module Point where

data Point x y = Point (x, y)

class Vector v where
  add :: v -> v -> v
  sub :: v -> v -> v
  mul :: Num k => k -> v -> v

instance (Num a, Num b) => Vector (Point a b) where
  add (Point (a, b)) (Point (c, d)) = Point (a + c, b + d)
  sub (Point (a, b)) (Point (c, d)) = Point (a - c, b - d)
  mul k (Point (a, b)) = Point (k * a, k * b)

person Brady Dean    schedule 08.10.2018    source источник
comment
Он знает это, но не знает, что a и b являются одним и тем же типом. В Haskell операнды (+), (-), (*) и т. д. имеют один и тот же тип. (+) :: Int -> Double -> Double нет.   -  person Willem Van Onsem    schedule 08.10.2018
comment
Хорошо, может быть, мне следует определить Point, чтобы он имел один и тот же тип для x и y.   -  person Brady Dean    schedule 08.10.2018
comment
не только для x и y, но и для k и x и, следовательно, k и y.   -  person Willem Van Onsem    schedule 08.10.2018
comment
Кортеж лишний; это просто ненужный слой косвенности. data Point x y = Point x y или (лучше) data Point x = Point x x достаточно.   -  person chepner    schedule 08.10.2018
comment
@WillemVanOnsem Есть ли способ указать, что k, x и y должны быть одного типа?   -  person Brady Dean    schedule 08.10.2018
comment
@BradyDean Конечно: data Point x = Point x x говорит, что Point имеет два значения одного и того же типа (и этот тип — x).   -  person MathematicalOrchid    schedule 09.10.2018


Ответы (1)


Проблема в том, что ваша подпись mul говорит, что v можно умножить на любой тип k, который имеет экземпляр Num: Int, Double, Complex Double и т. д. и т. д.

Но для векторных пространств вам нужно совсем другое: сказать, что для каждого v существует определенное k. Это можно сделать двумя способами (после исправления data Point x = Point x x как предложено в комментариях):

  1. используя класс многопараметрического типа с функциональной зависимостью ;

  2. с использованием связанных типов .

Первоначально я дал решения, используя оба, но может быть полезнее прочитать связанную документацию и попробовать ее самостоятельно.

person Alexey Romanov    schedule 08.10.2018