Простой способ думать об этом с точки зрения изображения, и легкий превратиться в код: Возьмите вектор (пкс - cX, pY - cY) от центра до точки. Разделитесь на его длину sqrt (и тому подобное), умножьтесь радиусом. Добавьте это к (cX, cY).
Ожидается функция с сигнатурой Num a => a
работать для любого типа в классе Num
. Реализация 5.0 :: Double
работает только для одного типа, а не для всех типов класса, поэтому компилятор жалуется.
Пример класса общая функция будет выглядеть так:
square :: (Num a) => a -> a
square x = x * x
Это работает для любого типа , который является Num
. Он работает с числами типа double, integer и любыми другими числами, которые вы хотите использовать. Из-за этого он может иметь сигнатуру универсального типа, которая просто требует, чтобы параметр находился в классе Num
. (Класс типа Num
необходим, потому что функция использует умножение на *
,
Чтобы добавить к этому ответу: Haskell не является объектно-ориентированным. Неверно, что Double
является подклассом Num
, поэтому вы не можете вернуть Double
, если обещаете вернуть полиморфное Num
значение. , как, например, в Java.
Когда вы пишете getN :: Num a => a
, вы обещаете вернуть значение, которое полностью полиморфно в пределах ограничения Num
. Фактически это означает, что вы можете использовать только функции из класса типов Num
, например +
, *
, -
и fromInteger
.
Ознакомьтесь с Экзистенциально количественно определенными типами .
Одним из способов решения этой проблемы было бы определение нового типа данных
data NumBox = forall n. Num n => NumBox n
. Вам потребуется -XExistentialQuantification
, чтобы заставить это работать.
Теперь вы можете написать что-то вроде
getN :: NumBox
getN = NumBox (5.0 :: Double)
Вы также можете определите список NumBox
как
let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ]