开发者

"Ambigous type variable" error when defining custom "read" function

While trying to compile the following code, which is enhanced version of read build on readMay from Safe package.

readI :: (Typeable a, Read a) => String -> a
readI str = case readMay str of
               Just x -> x 
               Nothing -> error ("Prelude.read failed, expected type: " ++ 
                                 (show (typeOf > (undefined :: a))) ++ 
                                 "String was: " ++ str)

I get an error from GHC:

WavefrontSimple.hs:54:81:

Ambiguous type variable `a' in the constraint:

`Typeable a'

arising from a use of `typeOf' at src/WavefrontSimple.hs:54:81-103

Probable fix: add a type signature that fixes these type variable(s)`

I don't understand why. What should be fixed to get what I meant?

EDIT: Ok, so the solution to use ScopedTypeVariables and forall a in type signature works. But why the following produces very similar error to the one above? The compiler should infer the right type since there 开发者_如何转开发is asTypeOf :: a -> a -> a used.

readI :: (Typeable a, Read a) => String -> a
readI str = let xx = undefined in
            case readMay str of
              Just x -> x `asTypeOf` xx
              Nothing -> error ("Prelude.read failed, expected type: " 
                               ++ (show (typeOf xx)) ++ 
                                "String was: " ++ str)


The latter doesn't work because the type of xx is the same as the type of undefined -- i.e., "forall a. a." The fact that you force xx to be used with one concrete type with the asTypeOf operator doesn't mean that it is less polymorphic everywhere else.


The a in undefined :: a and readI :: (Typeable a, Read a) => String -> a are not the same type a. It's as if you wrote readI :: ... a; readI = ... (undefined :: b).

{-# LANGUAGE ScopedTypeVariables #-}

readI :: forall a. (Typeable a, Read a) => String -> a
...

The scoped type variables extension changes the Haskell language to allow you to carry the type variable a from outer scope to inner scope, if explicitly quantified with forall.


I'm not sure why your x `asTypeOf` xx doesn't seem to work. This does, though:

readI :: (Typeable a, Read a) => String -> a
readI str = xx where
    xx = case readMay str of
             Just x -> x
             Nothing -> error ("Prelude.read failed, expected type: "
                              ++ (show (typeOf xx)) ++
                               "String was: " ++ str)


I think you need scoped type variables.

{-# LANGUAGE ScopedTypeVariables #-}
readI :: forall a. (Typeable a, Read a) => String -> a
readI str = case readMay str of
               Just x -> x 
               Nothing -> error ("Prelude.read failed, expected type: " ++ 
                                 (show (typeOf > (undefined :: a))) ++ 
                                 "String was: " ++ str)

See also.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜