Thank you!  I agree that what I'm doing isn't useful from an application perspective, but this turned out to be very useful for comprehension.

It was the 

rad :: a b -> b

that I was missing.  Two type variables-- one for Angle and one for Float.  This now compiles just fine:

data Angle a = Radians a
             | Degrees a
             deriving (Eq, Show)

class Angular a where
  rad :: (Floating b) => a b -> b
  rad x = pi * (deg x) / 180
  deg :: (Floating b) => a b -> b
  deg x = 180 * (rad x) / pi

instance Angular Angle where
    rad (Radians x) = x
    deg (Degrees x) = x 

x :: Angle Float
x = Radians (pi / 2)

y :: Float
y  = deg x

It just doesn't execute, because of a non-exhaustive pattern for deg.  I guess that makes sense-- the default functions are per type, not per value constructor...

Changing my instance definition to this:

instance Angular Angle where
    rad (Radians x) = x
    rad (Degrees x) = pi * x / 180
    deg (Radians x) = 180 * x / pi
    deg (Degrees x) = x 

resolves the problem.

Thanks again for the help.  I'm now that much further down the type system learning curve...

Cheers--
 Greg


On Aug 23, 2010, at 8:06 PM, Tobias Brandt wrote:

You don't need a type class, you can just define your functions with pattern matching:

rad :: Angle a -> a
rad (Radians x) = x
rad (Degrees x) = pi * (deg x) / 180

deg :: Angle a -> a
deg (Radians x) = 180 * (rad x) / pi
deg (Degrees x) = x

Alternatively, you can define Radians and Degrees as separate types and use a type class:

data Radians a = Radians a
data Degrees a = Degrees a

class Angular a where
    rad :: a b -> b
    deg :: a b -> b

instance Angular Radians where
    rad (Radians x) = x
    deg (Radians x) = 180 * (rad x) / pi

instance Angular Degrees where
    rad (Degrees x) = pi * (deg x) / 180
    deg (Degrees x) = x

This would be extensible, but it this case not really useful.