Подход Haskell должен иметь разные типы для Complex Float
и Complex Int
, а не пытаться объединить их в один тип. С классами типа вы можете определить все эти типы сразу:
data Complex a = C a a
instance Num a => Num (Complex a) where
(C x y) + (C u v) = C (x+u) (y+v)
(C x y) * (C u v) = C (x*u-y*v) (x*v+y*u)
fromInteger n = C (fromInteger n) 0
...
Это сразу определяет Complex Int
, Complex Double
, Complex Rational
и т.д. На самом деле он даже определяет Complex (Complex Int)
.
Обратите внимание, что это не определяет, как добавить Complex Int
в Complex Double
. Дополнение (+) по-прежнему имеет тип (+) :: a -> a -> a
, поэтому вы можете только добавить Complex Int
в Complex Int
и Complex Double
в другой Complex Double
.
Для добавления номера различных типов вы должны явным образом преобразовать их, например .:
addIntToComplex :: Int -> Complex Double -> Complex Double
addIntToComplex n z = z + fromIntegral n
Посмотрите http://www.haskell.org/tutorial/numbers.html раздел 10.3 для более полезных функций преобразования между классами числовых типов в Haskell.
Update:
В ответ на ваши замечания, я хотел бы предложить больше ориентированы на операции и в меньшей степени на типах.
Для примера рассмотрим следующее определение:
onethird = 1/3
Это представляет родовое «1/3» значение во всех классах номер:
import Data.Ratio
main = do
putStrLn $ "as a Double: " ++ show (onethird :: Double)
putStrLn $ "as a Complex Double: " ++ show (onethird :: Complex Double)
putStrLn $ "as a Ratio Int: " ++ show (onethird :: Ratio Int)
putStrLn $ "as a Complex (Ratio Int): " ++ show (onethird :: Complex (Ratio Int))
...
В некотором смысле Haskell давайте «пользователь» решить какой числовой тип выражение должно быть оценено как.
Как вы ожидаете, что сможете добавить 'ComplexNum' формы' con2 (Complex Float) 'в один из форм' con3 (Complex Rational) '? –
@Tom, предоставляя эти функции самостоятельно («продвижение»/типы конвертирования и т. Д.). Число включает в себя все представления чисел, которые я хочу использовать как Int, Integer и т. Д., И я буду использовать дробное число для Number, а затем предоставить свой собственный сложный класс с экземпляром Дробный A => Дробный (комплекс a) '. Я надеялся, что кто-то знает, как это сделать, используя Data.Complex вместо моего собственного. – user3125280
@ user3125280 Почему? Что бы вы потеряли знания и контроль над типом? –