21 Dec 19:34
Re: nice simple problem for someone struggling....
David Menendez <dave <at> zednenem.com>
2007-12-21 18:34:19 GMT
2007-12-21 18:34:19 GMT
On Dec 21, 2007 12:47 PM, Nicholls, Mark <Nicholls.Mark <at> mtvne.com> wrote:
Let me resend the code…as it stands….
module Main where
data SquareType numberType = Num numberType => SquareConstructor numberType
class ShapeInterface shape where
area :: Num numberType => shape ->numberType
data ShapeType = forall a. ShapeInterface a => ShapeType a
instance (Num a) => ShapeInterface (SquareType a) where
area (SquareConstructor side) = side * side
Part of the problem is that GHC's error messages have to account for a lot of complex typing extensions you aren't using, so they aren't clear. I'll try to explain what's going wrong.
If you look at the function,
area (SquareConstructor side) = side * side
in isolation (that is, not as part of the class instance), it has the type "forall a. Num a => SquareConstructor a -> a".
The function in the class declaration has type "forall a b. (ShapeInterface a, Num b) => a -> b". The problem is that a and b are independent variables, but the instance declaration for SquareType a requires them to be related.
I'm not sure which way you were trying to parameterize things, but here are some possibilities:
(1) If every shape type is parameteric, then you can make ShapeInterface a class of type constructors.
class ShapeInterface shape where
area :: Num a => shape a -> a
instance ShapeInterface SquareType where
area (SquareConstructor side) = side * side
(2) If only some shape types are parametric, you can use a multi-parameter type class to express a relationship between the shape type and the area type:
class ShapeInterface shape area where
area :: shape -> area
instance (Num a) => ShapeInterface (SquareType a) a where
area (SquareConstructor side) = side * side
(3) If you only need to be parameteric over some subset of numeric types, you can use conversion functions:
class ShapeIterface shape where
area :: shape -> Rational
class (Real a) => ShapeInterface (SquareType a) where
area (SquareConstructor side) = toRational (side * side)
(Equivalently, you can replace Rational and Real with Integer and Integral.)
If you look at the function,
area (SquareConstructor side) = side * side
in isolation (that is, not as part of the class instance), it has the type "forall a. Num a => SquareConstructor a -> a".
The function in the class declaration has type "forall a b. (ShapeInterface a, Num b) => a -> b". The problem is that a and b are independent variables, but the instance declaration for SquareType a requires them to be related.
I'm not sure which way you were trying to parameterize things, but here are some possibilities:
(1) If every shape type is parameteric, then you can make ShapeInterface a class of type constructors.
class ShapeInterface shape where
area :: Num a => shape a -> a
instance ShapeInterface SquareType where
area (SquareConstructor side) = side * side
(2) If only some shape types are parametric, you can use a multi-parameter type class to express a relationship between the shape type and the area type:
class ShapeInterface shape area where
area :: shape -> area
instance (Num a) => ShapeInterface (SquareType a) a where
area (SquareConstructor side) = side * side
(3) If you only need to be parameteric over some subset of numeric types, you can use conversion functions:
class ShapeIterface shape where
area :: shape -> Rational
class (Real a) => ShapeInterface (SquareType a) where
area (SquareConstructor side) = toRational (side * side)
(Equivalently, you can replace Rational and Real with Integer and Integral.)
--
Dave Menendez <dave <at> zednenem.com>
<http://www.eyrie.org/~zednenem/>
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe <at> haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RSS Feed