9

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

考虑以下 GHCi 会话:

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

ghci -XNoImplicitPrelude让我们用and试试这个classy-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]]

我假设 GHC 根本无法正确解析多维列表的类型。有什么办法可以帮助它而不求助于它(Prelude.head . Prelude.head)

4

1 回答 1

11

正如评论中已经提到的,classy prelude 的head函数仅适用于类型系统保证至少具有一个元素的可遍历,因此它不必是部分的。因为您的所有列表都至少有一个元素,所以您可以只使用非空列表类型:

head . head $ mlcons (mlcons 1 $ mlcons 2 $ toMinLenZero []) $ mlcons (mlcons 3 $ mlcons 4 $ toMinLenZero []) $ toMinLenZero [] :: Int
-- 1

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

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

unsafeHead . unsafeHead [[1,2],[3,4]]
-- 1

该模块中还有一个headMay,如果您想以不同的方式处理故障而不会使整个程序崩溃,则可以使用该模块。

于 2014-02-26T00:42:28.903 回答