[Haskell-cafe] nice simple problem for someone struggling....

David Menendez dave at zednenem.com
Fri Dec 21 13:34:19 EST 2007

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

    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.)

It may be that none of these are what you want. There are other, more
complex possibilities, but I expect they're overkill.

Dave Menendez <dave at zednenem.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20071221/336dc7cb/attachment.htm

More information about the Haskell-Cafe mailing list