尝试编译以下代码时,这是安全包中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
可能的修复:添加修复这些类型变量`
我不明白为什么。什么应该修复才能得到我的意思?
编辑:好的,因此在类型签名中使用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)
答案 0 :(得分:2)
a
和undefined :: 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)