如何指定内联类型中使用的类型变量,是不是与函数定义中使用的类型变量相同?
Posted
技术标签:
【中文标题】如何指定内联类型中使用的类型变量,是不是与函数定义中使用的类型变量相同?【英文标题】:How do I specify a type variable used in an inline type, is the same as a type variable used in a function definition?如何指定内联类型中使用的类型变量,是否与函数定义中使用的类型变量相同? 【发布时间】:2014-06-24 20:42:06 【问题描述】:(抱歉,如果我的术语有误)。
我正在尝试编写一个处理异常的包装函数:如果给定的IO
动作抛出,它返回Nothing
(当然在IO
上下文中),但如果给定的IO
动作成功,它返回Just v
。
tryMaybe :: IO a -> IO (Maybe a)
tryMaybe action = do
result <- (try action) :: IO (Either SomeException a)
return $ case result of
Left _ -> Nothing
Right v -> Just v
这会导致编译器错误消息:
Couldn't match type `a' with `a1'
`a' is a rigid type variable bound by
the type signature for tryMaybe :: IO a -> IO (Maybe a)
at src/Database.hs:33:13
`a1' is a rigid type variable bound by
an expression type signature: IO (Either SomeException a1)
at src/Database.hs:35:15
Expected type: IO a1
Actual type: IO a
In the first argument of `try', namely `action'
我猜第一行中的类型变量a
与第三行中的a
不同——它们恰好在源代码中具有相同的名称,并且编译器具有在错误消息中将其重命名为a1
。
那么我如何告诉 Haskell 这些是相同的类型呢?
【问题讨论】:
你试过ScopedTypeVariables
吗?
相关解释在这里:***.com/questions/15800878/…
【参考方案1】:
需要开启ScopedTypeVariables
扩展,并将顶层函数的类型签名改为forall a .
开头:
-# LANGUAGE ScopedTypeVariables #-
...
tryMaybe :: forall a . IO a -> IO (Maybe a)
...
forall
语法将类型变量a
带入tryMaybe
整个主体的范围内,而不是仅限于默认的类型签名。这主要是历史上的反常现象,而非刻意的设计。
【讨论】:
啊哈是的,它排序了。我知道 GHC 在这里试图保持与 Haskell 98 的向后兼容性,但我会想到关于类型变量阴影的警告(如果这是正确的术语),加上调查该语言扩展的提示,可能对像我这样的新手有帮助.啊,我生活和学习。非常感谢! @stusmith 我认为阴影警告是个好主意。您应该提交 ghc 增强票。以上是关于如何指定内联类型中使用的类型变量,是不是与函数定义中使用的类型变量相同?的主要内容,如果未能解决你的问题,请参考以下文章