定义自定义“读取”功能时出现“模糊类型变量”错误

时间:2010-03-24 22:54:24

标签: haskell serialization typeclass

尝试编译以下代码时,这是安全包中readMay上的read build的增强版本。

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)

我从GHC收到错误:

  

WavefrontSimple.hs:54:81:
          约束中的模糊类型变量“a”:
           `Typeable a'
             在src / WavefrontSimple.hs中使用`typeOf'引起的:54:81-103
         可能的修复:添加修复这些类型变量`

的类型签名

我不明白为什么。什么应该修复才能得到我的意思?

编辑:好的,因此在类型签名中使用ScopedTypeVariablesforall a的解决方案可行。但为什么以下产生与上述错误非常相似的错误?编译器应该推断出正确的类型,因为使用了asTypeOf :: a -> a -> a

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)

3 个答案:

答案 0 :(得分:2)

aundefined :: a中的readI :: (Typeable a, Read a) => String -> a不是类型 a。就好像你写了readI :: ... a; readI = ... (undefined :: b)

{-# LANGUAGE ScopedTypeVariables #-}

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

如果使用a明确量化,scoped type variables扩展名会更改Haskell语言,以允许您将类型变量 forall从外部作用域带到内部作用域


我不确定为什么你的x `asTypeOf` xx似乎不起作用。但这确实如此:

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)

答案 1 :(得分:2)

后者不起作用,因为xx的类型与undefined的类型相同 - 即“forall a.a”。你使用asTypeOf运算符强制xx与一个具体类型一起使用这一事实并不意味着它在其他任何地方都不那么多态。

答案 2 :(得分:1)

我认为你需要范围类型变量。

{-# 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