function - 理解 Haskell 中的函数定义和类型

标签 function haskell types

我正在尝试用 Haskell 编写一个简单的工具作为学习练习,但遇到了一些我无法弄清楚的事情。这是一个简单的示例来说明它。

idMap :: a -> a
idMap x = map id x

main = do
    print $ idMap [1, 2]

根据我的理解,这个例子应该在运行时编译并打印[1, 2]。但是,如果编译失败并显示以下消息:

source_file.hs:2:18: error:
    • Couldn't match expected type ‘[b0]’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          idMap :: forall a. a -> a
        at source_file.hs:1:10
    • In the second argument of ‘map’, namely ‘x’
      In the expression: map id x
      In an equation for ‘idMap’: idMap x = map id x
    • Relevant bindings include
        x :: a
          (bound at source_file.hs:2:7)
        idMap :: a -> a
          (bound at source_file.hs:2:1)

这是有道理的,因为 map 的签名是 (a -> b) -> [a] -> [b] 所以输入类型不一定与输出类型相同,但 id 的签名是 a -> a 所以肯定可以得出 map id 会有(a -> a) -> [a] -> [a] 的签名?

我不太明白的第二部分是为什么这是一个异常(exception),因为所有类型(ab 如上所述)都是 Integer。这对我来说很有意义,因为 idMap 的签名是 a -> a,所以只有在输出类型为预计与输入类型不同。

最后,我怎样才能使这段代码真正起作用?我的真实代码有点复杂,我依赖于代码中其他地方的输出类型与输入类型相匹配,所以我不想更改 idMap 的签名,我想知道我需要用该签名编写一个函数。

最佳答案

您正在将 idMap 应用于列表。因此,我们知道参数类型应该是某种列表类型。此外,您希望返回类型是一个列表 ([1,2]),因此返回类型也应该是一个列表。由于 id 函数是完全多态的 (a -> a),我们可以将其映射到任何类型的列表 a 并返回相同类型 a 的项目列表。因此,您的最终类型签名应该是 [a] -> [a]

关于你的第二个问题,虽然参数类型和返回类型都是相同的,但a -> a 的类型并非对所有类型都是正确的一个。根据 map 的类型签名,idMap 必须 接受列表参数。我们可以为比必要的约束更多但不少于约束的函数声明类型签名。

关于function - 理解 Haskell 中的函数定义和类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41270002/

相关文章:

c - 使用指针将 2 个矩阵相加

Javascript - 如何将匿名方法作为变量调用并访问其属性和方法?

javascript - 函数未运行/未正确调用

performance - IORef 和 STRef 的编译

types - rust :特质作为返回类型

scala - 利用 Scala 匹配表达式中案例类的类型约束

android - 关于 C++ 中的函数名

Haskell - 函数不适用于无限列表

映射中的 Haskell 错误

MySQL 截断 GROUP_CONCAT 函数的连接结果