在尝试编译以下代码时,这是来自Safe包的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”:在src / WavefrontSimple.hs中使用
typeOf'产生的
Typeable a':54:81-103可能的修复:添加类型签名修复了这些类型变量`
我不明白为什么 . 得到我的意思应该修复什么?
EDIT: 好的,所以在类型签名中使用 ScopedTypeVariables
和 forall 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 回答
我认为你需要范围类型变量 .
See also .
后者不起作用,因为
xx
的类型与undefined
的类型相同 - 即"forall a. a."强制xx与asTypeOf运算符一起使用的事实并不意味着它的多态性较小在其他地方 .undefined :: a
和readI :: (Typeable a, Read a) => String -> a
中的a
与a
的类型不同 . 就像你写了readI :: ... a; readI = ... (undefined :: b)
一样 .scoped type variables扩展名更改Haskell语言,以允许您将类型变量
a
从外部作用域携带到内部作用域,如果使用forall
明确量化的话 .我不确定为什么你的
x
asTypeOfxx
似乎不起作用 . 但这确实如此: