Classy-Prelude(head.head)

Uli*_*ler 9 haskell classy-prelude

我正试图将几个项目转换成classy-prelude目前.虽然大多数行为对我来说都很简单,但(head . head)在简单的2D列表中给出了神秘的错误.

考虑以下GHCi会话:

Prelude> (head . head) [[1,2],[3,4]]
1
Run Code Online (Sandbox Code Playgroud)

让我们试试这个用ghci -XNoImplicitPreludeclassy-prelude:

> import ClassyPrelude
ClassyPrelude> (head . head) [[1,2],[3,4]]

<interactive>:10:1:
    Couldn't match type `MinLen (Succ nat1) mono1' with `[[t0]]'
    Expected type: [[t0]] -> Element mono0
      Actual type: MinLen (Succ nat1) mono1 -> Element mono0
    The function `head . head' is applied to one argument,
    but its type `MinLen (Succ nat1) mono1 -> Element mono0'
    has only one
    In the expression: (head . head) [[1, 2], [3, 4]]
    In an equation for `it': it = (head . head) [[1, 2], [3, 4]]
Run Code Online (Sandbox Code Playgroud)

我认为GHC根本无法正确解析多维列表的类型.我有什么方法可以帮助它而不诉诸(Prelude.head . Prelude.head)

ben*_*ofs 11

正如在评论中已经提到的那样,优雅前奏的头部函数仅适用于遍历,这些遍历由类型系统保证至少有一个元素,因此它不必是部分的.因为您的所有列表至少有一个元素,所以您可以使用非空列表类型:

head . head $ mlcons (mlcons 1 $ mlcons 2 $ toMinLenZero []) $ mlcons (mlcons 3 $ mlcons 4 $ toMinLenZero []) $ toMinLenZero [] :: Int
-- 1
Run Code Online (Sandbox Code Playgroud)

(以函数开头的函数ml全部来自MinLen模块mono-traversable,由其重新导出classy-prelude)

如果您只想要该Prelude.head函数的行为,则可以从包中再次使用unsafeHeadmono-traversable并默认导出:

unsafeHead . unsafeHead [[1,2],[3,4]]
-- 1
Run Code Online (Sandbox Code Playgroud)

还有headMay该模块,可如果你喜欢处理失败不同,不会崩溃的整个程序中使用英寸

  • 很好的答案,我也会投入`headEx`.它与`unsafeHead`之间的区别在于`unsafeHead`可能导致某些数据类型的段错误(特别是`Vector`和`ByteString`),而`headEx`保证在空容器上抛出异常. (2认同)