haskell - Haskell 中的模块签名是什么?

标签 haskell haskell-backpack

我最近发现了 Haskell 的“模块签名”功能。正如我发现的那样,它们被放入 .hsig文件并以 signature 开头关键字而不是 module .
这种文件的示例语法可能看起来像

signature Str where

data Str
empty :: Str
append :: Str -> Str -> Str

但是,我无法想象人们会如何以及为什么会使用它们。你能解释一下他们解决了哪些问题以及如何正确利用它们吗?

他们强烈提醒我在 OCaml (link) 中可以看到的模块系统,它也有模块签名和单独的实现,但我无法确定这两个概念有多接近。有什么关系吗?

最佳答案

它们与 OCaml 模块系统相关,但有一些重要区别:

  • 签名在语言中定义(在 .hsig 文件中),但与 OCaml 不同,它们不在语言中实例化。相反,包管理器控制实例化(目前只有 Cabal 提供)。模块永远不知道它们是在导入抽象签名还是实际模块。
  • 实现模块对签名一无所知,也不直接引用它们。如果定义恰好兼容,则任何现有模块都可以实现签名。
  • 实例化是由某些编译单元(可执行文件、库、测试套件...)的依赖项中的模块名称和签名名称重合触发的。当名称重合时,会发生一个称为“签名匹配”的过程,以验证类型和定义是兼容的。

  • “幸福的道路”是在您的程序中,您依赖于一些具有签名“洞”的库,以及另一个提供具有相同名称的实现模块的库。然后签名匹配会自动发生。当名称不匹配时,或者我们需要签名使用库的多个实例化,我们必须重命名 mixins 中的签名和/或模块。 Cabal 文件的部分。

    至于为什么模块签名可能有用,请考虑 bytestring ,迄今为止在 Haskell 中处理二进制数据的最流行的库。但还有其他的,例如 stdio及其 Bytes 类型。

    假设您正在编写自己的使用二进制数据的库,并且您不想强制用户进入 stdio 或 bytestring。 .你有什么选择?
  • 一种是创建类似于 Bytelike 的东西。类并用它参数化所有函数。您还需要为每个包含字节的数据类型添加一个类型参数。
  • 另一种方法是创建一个定义抽象二进制数据类型及其所需的所有操作的签名。您的库将使用签名,并保持“无限期”,直到用户在创建自己的库时同时依赖您的库和合适的实现。

  • 从用户的角度来看,typeclass 的解决方案并不能令人满意。用户知道他想使用 ByteStringBytes , 只是其中之一。该决定将不依赖于某些运行时标志,并将在他的程序范围内保持不变。然而,他必须处理一个更复杂的 API,每时每刻都会提醒他已经决定的问题。

    如果他做出一次决定,将其写入他的 .cabal 文件,然后从那时起处理更简单的 API,那就更好了。

    关于haskell - Haskell 中的模块签名是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55078118/

    相关文章:

    haskell - 背包使用示例

    performance - 使用 Haskell 进行竞争性编程

    haskell - 你如何在 Haskell 中使用 TypeApplications?

    list - 编写基本的 haskell 函数,获取 Int x 并在 [1..x] 上执行函数

    haskell - 使用 GHC 的分析统计数据/图表来识别问题区域/提高 Haskell 代码的性能

    haskell - 另一个 monad 下的有状态代码

    haskell - 如何在 Haskell 中按模块参数化函数?