Question about classes from a Haskell newbie.

Hi, I'm new to Haskell and even newer to this list. I have over 20 years of experience in C or C++. For fun, I decided to write a Fourier transform in Haskell. It would be convenient if I had a function that converts any real or complex number into a complex number. My attempt at doing this is below. Hugs produces errors when I try to load this code. Essentially, I'm trying to define a class called ConvertibleToComplex. There is a function in this class called toComplex. toComplex has the type: class ConvertibleToComplex a where toComplex :: RealFloat b => a -> Complex b I'd like some instances of toComplex to return a Complex Double while other instances return a Complex Float. Doing this sort of thing in C++ is fairly easy. However, I get the feeling that I'm pushing the Haskell type system to do something it isn't designed to do. Is there a way to define ConvertibleToComplex so that toComplex's return type is generic and a particular instance of ConvertibleToComplex decides what the return type is? Here is my attempt at doing this. If someone can give me some pointers on how to make this work, I'd appreciate it. module Main where import Complex -------------------------------------------------------------------------------- -- toComplex should convert a real or complex number to a complex number. -- -- Here's my goal for the type of toComplex. Given: -- f :: Float -- d :: Double -- cf :: Complex Float -- cd :: Complex Double -- -- When toComplex is applied to these, I'd like it to evaluate to the -- following types: -- -- toComplex f :: Complex Float -- toComplex d :: Complex Double -- toComplex cf :: Complex Float -- toComplex cd :: Complex Double class ConvertibleToComplex a where toComplex :: RealFloat b => a -> Complex b -- If I uncomment the following code, Hugs produces errors: -- ERROR "c:\tmp\test2.hs":29 - Inferred type is not general enough -- *** Expression : toComplex -- *** Expected type : (ConvertibleToComplex Float, RealFloat a) => Float -> Complex a -- *** Inferred type : (ConvertibleToComplex Float, RealFloat Float) => Float -> Complex Float {- instance ConvertibleToComplex Float where toComplex f = f :+ 0 instance ConvertibleToComplex Double where toComplex d = d :+ 0 instance ConvertibleToComplex (Complex a) where toComplex c = c -}

Jeff.Harper@handheld.com a écrit :
Hi,
I'm new to Haskell and even newer to this list. I have over 20 years of experience in C or C++.
For fun, I decided to write a Fourier transform in Haskell. It would be convenient if I had a function that converts any real or complex number into a complex number. My attempt at doing this is below. Hugs produces errors when I try to load this code.
Essentially, I'm trying to define a class called ConvertibleToComplex. There is a function in this class called toComplex. toComplex has the type:
class ConvertibleToComplex a where toComplex :: RealFloat b => a -> Complex b
I'd like some instances of toComplex to return a Complex Double while other instances return a Complex Float. Doing this sort of thing in C++ is fairly easy. However, I get the feeling that I'm pushing the Haskell type system to do something it isn't designed to do. Is there a way to define ConvertibleToComplex so that toComplex's return type is generic and a particular instance of ConvertibleToComplex decides what the return type is?
I think you misunderstand the meaning of the constraint ! toComplex :: (RealFloat b) => a -> Complex b means the type of "b" needs to be a "RealFloat" and that it will be inferred from the context where the function "toComplex" is called ! It does not mean it can return any value of a type instance of "RealFloat". For example, the instance for "Float" should be something like: instance ConvertibleToComplex Float where toComplex f = ( fromRational . toRational ) f :+ fromInteger 0 And the same implementation hold for "Double" also ... (By the way I don't know if the implementation is optimal or whatever ... but it does work ;) ). Pierre -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68

On 5/23/05, Jeff.Harper@handheld.com
Hi,
I'm new to Haskell and even newer to this list. I have over 20 years of experience in C or C++.
For fun, I decided to write a Fourier transform in Haskell. It would be convenient if I had a function that converts any real or complex number into a complex number. My attempt at doing this is below. Hugs produces errors when I try to load this code.
Essentially, I'm trying to define a class called ConvertibleToComplex. There is a function in this class called toComplex. toComplex has the type:
class ConvertibleToComplex a where toComplex :: RealFloat b => a -> Complex b
I don't think you want an arbitrary type 'b'. Try: (pass -98 to Hugs or -fglasgow-exts to GHCi when loading this code) import Complex class ConvertibleToComplex a b | a -> b where toComplex :: RealFloat b => a -> Complex b instance ConvertibleToComplex Float Float where toComplex f = f :+ 0 instance ConvertibleToComplex Double Double where toComplex d = d :+ 0 instance ConvertibleToComplex (Complex a) a where toComplex c = c -- Friendly, Lemmih
participants (3)
-
Jeff.Harper@handheld.com
-
Lemmih
-
Pierre Barbier de Reuille