Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Brady DeanОтветов: 1

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

typeclasshaskell

Ответы

Ответ 1 · рейтинг 1 · Alexey Romanov

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

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

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

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы