开发者

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

开发者 https://www.devze.com 2022-12-24 05:51 出处:网络
While trying to compile the following code, which is enhanced version of read build on readMay from Safe package.

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

精彩评论

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