[Haskell-cafe] Typeclass question
Stefan O'Rear
stefanor at cox.net
Sun Dec 3 12:37:02 EST 2006
On Sun, Dec 03, 2006 at 12:26:30PM -0500, Jonathan Tang wrote:
> I've got what's probably a beginner's question, but I'm out of ideas
> for solving it. It looks like it tripped me up in "Write Yourself a
> Scheme..." too, since the code there seems like it's arranged so I
> never ran into it...
>
> I've got a couple functions:
>
> binop :: (AmbrosiaData -> AmbrosiaData -> AmbrosiaM AmbrosiaData) ->
> AmbrosiaM ()
> binop operator = do
> second <- popStack
> first <- popStack
> result <- operator first second
> pushStack result
>
> numNumOp :: Num a => (a -> a -> a) -> AmbrosiaData -> AmbrosiaData ->
> AmbrosiaM AmbrosiaData
> numNumOp op (Number val1) (Number val2) = return $ Number $ op val1 val2
> numNumOp op (Float val1) (Float val2) = return $ Float $ op val1 val2
> numNumOp op _ _ = throwError . TypeMismatch $ "Number"
When you say Num a => (a -> a -> a) -> ..., what that means is:
numNumOp :: forall a. Num a => ((a -> a -> a) -> AmbrosiaData -> AmbrosiaData -> AmbrosiaM AmbrosiaData)
That is, what you pass must be a single type. It looks like what you
want is:
numNumOp :: (forall a. Num a => (a -> a -> a)) -> AmbrosiaData -> AmbrosiaData -> AmbrosiaM AmbrosiaData
Notice that forall is in the argument - thus numNumOp must recieve a
polymorphic argument. This is called rank-2 polymorphism, and numNumOp
is a rank-2 polymorphic function. Unfortunately, it turns out that
allowing foralls inside function arguments makes typechecking much
harder, in general impossible. GHC allows it but requires explicit type
annotations on all rank-2 polymorphic functions. Haskell98 forbids
rank-2 polymorphism altogether (and explicit foralls, for that matter).
More information about the Haskell-Cafe
mailing list