haskell - 如何在let绑定(bind)中添加类型注释

标签 haskell

我是 Haskell 的初学者,我发现错误消息真的很难理解(我想它会随着时间的推移而出现)。不管怎样,为了帮助我理解我的错误,我尝试在 let 绑定(bind)中添加带有类型注释的中间变量,发现它会生成更多错误,即使我的类型(我认为)是正确的。

示例;

f :: a -> a
f x = 
    let x' = x :: a
    in x'

产生以下错误

test.hs:3:12:
Couldn't match expected type `a2' with actual type `a'
  `a2' is a rigid type variable bound by
       an expression type signature: a2 at test.hs:3:12
  `a' is a rigid type variable bound by
      the type signature for f :: a -> a at test.hs:1:6
In the expression: x :: a
In an equation for x': x' = x :: a
In the expression: let x' = x :: a in x

我做错了什么还是不可能这样做?

最佳答案

解决方案

您需要 ScopedTypeVariables 扩展才能使其工作,如下所示:

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a. a -> a
f x = 
    let x' = x :: a
    in x'

说明

如果你有这样的类型签名

f :: a -> a

那么它表明f是多态的并且适用于a的任何选择。所以 f 可能是 用于 Int -> Int 类型,或 Bool -> Bool 类型,或 [Int -> Bool] -> [Int -> Bool] 类型 – 无论你喜欢什么。

如果你有这样的类型注释

x :: a

这意味着类似的事情,即 x 应该可用于您选择的任何类型。但你的情况并非如此。外部函数 f 是多态的,但在函数内部,x 必须具有与a相同的类型用户已选择外部x。默认情况下,Haskell 不会在不同类型签名和注释中出现的类型变量之间建立任何联系。但是,您可以通过启用 ScopedTypeVariables 扩展来告诉它这样做。现在,通过在 a -> a 前面添加 forall a.,您可以显式指示 Haskell 将 a 作为特定类型变量在f 的定义。如果您随后注释 x::a,它会引用外部 a,而不是新的多态 a

关于haskell - 如何在let绑定(bind)中添加类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22436402/

相关文章:

Haskell:如何测试未编译的代码?

haskell - 类型相等函数

haskell - 扩展无类型 Lambda 演算实现以涵盖简单类型 Lambda 演算需要什么?

haskell - 是否可以从 Haskell 中数据类型的可能值生成列表?

Haskell,一个参数的多个类型类

haskell - 为什么此功能无法进行类型检查?

haskell - 为除一种特定类型之外的所有类生成一个实例

haskell - 多态类约束实例

haskell - Foldr 递归模式中的 f [] = v 是什么意思?

debugging - ExitFailure 1 再次出现在 `Hat`