Подход 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.
Обновление:
В ответ на ваши комментарии я бы предложил больше сосредоточиться на операциях, а не на типах.
Например, рассмотрим это определение:
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 позволяет «пользователю» решать, какому числовому типу следует оценивать выражение.
person
ErikR
schedule
26.01.2014
ComplexNum
формыcon2 (Complex Float)
к формеcon3 (Complex Rational)
? - person Tom Ellis   schedule 26.01.2014instance Fractional A => Fractional (Complex a)
. Я надеялся, что кто-нибудь знает, как это сделать, используя Data.Complex вместо моего собственного. - person user3125280   schedule 26.01.2014instance Complex Number
со всеми этими преобразованиями типов, реализованными вручную. Вы не можете ожидать, что компилятор сделает это за вас! - person Tom Ellis   schedule 26.01.2014instance Num Number
). В любом случае, довольно неясно, что вы пытаетесь сделать. Вы можете сформировать тип данныхComplex Number
. Хорошо. Это просто парыNumber
. У него не будет автоматического экземпляраNum
, если вы не предоставите экземплярRealFloat
дляNumber
(экземпляр, который вряд ли имеет смысл в любом случае). - person Tom Ellis   schedule 26.01.2014data Foo = N Number | C (Complex Number)
. Я не знаю, что вы подразумеваете под ComplexClass, но я сомневаюсь, что вам это нужно. Вам действительно нужен экземплярNum
, но, поскольку у вас все равно есть все эти преобразования типов, которые нужно писать вручную, вряд ли это кажется дополнительной трудностью. - person Tom Ellis   schedule 26.01.2014