【问题标题】:Second most recent list item Haskell第二个最近的列表项 Haskell
【发布时间】:2014-09-16 14:03:21
【问题描述】:

我正在尝试获取 Haskell 列表中的第二项。我认为最好的方法是获取列表尾部的头部。

secondMostRecentChoice :: History -> Choice // a choice is just a Bool like Bake | NoBake
secondMostRecentChoice [] = "Not Enough History"
secondMostRecentChoice history = 
    if ( length history == 1 ) 
        then "Still Not Enough History"
    else if (length history >= 2)
        then (head [b | (head a,b) <- history]) //Here is the problem
        else "Not supposed to be here"
    else "Not supposed to be here"

但我得到以下信息:

模式中的解析错误:head
可能是因为缺少“做”?

为什么我需要do 或者这是一个错误的建议?

【问题讨论】:

  • 是的,这是一个错误的建议。你可以写你想要的,因为head [b | (a:b:_) &lt;- history]a 已经是一个“头”了。但是,如果可以避免的话,您应该永远测量列表中的length。正如一些答案所建议的那样,在这里您可以通过将函数本身定义为模式匹配(a.o.t. 在列表理解中使用模式匹配)来避免它。

标签: haskell


【解决方案1】:

做到这一点的最短方法就是模式匹配它。

secondElem :: [a] -> Maybe a
secondElem (_:x:_) = Just x
secondElem _       = Nothing

【讨论】:

    【解决方案2】:

    我会使用模式匹配,因为它更清楚故障模式是什么:

       second :: [a] -> a
       second []      = error "Empty list"
       second [x]     = error "Singleton list"
       second (_:x:_) = x
    

    更清楚,不是吗?使规范显而易见。

    【讨论】:

    • head[a] -&gt; a 而不是 Maybe a 这不是疏忽吗?在这种情况下看到你error,我有点惊讶。
    • @BartekBanachewicz 只是表示如果列表太小会导致只能在 IO monad 中捕获的异常。尽管它确实提供了比Maybe a 更好的错误消息报告。
    • 为什么不Either String a,或者其他通用的MonadError呢?我不想把这个评论线程拖得太多,但这似乎令人费解。
    • @BartekBanachewicz 我想这只是在 SO 答案框中更容易输入的内容。它可以很容易地用 s/error/fail/s/= x/= return x/ 重构
    • 没有规范。使用模式匹配可以清楚地说明规范中的漏洞在哪里。那些漏洞可以用 Either 或 Maybe 来填补。
    【解决方案3】:

    获取第二项最简单的方法是使用!! 中缀运算符。它允许您访问列表中的特定项目。通常,对于大多数列表来说,这太慢了,但因为它只是第二项,所以这并不重要。

    【讨论】:

    • 如果列表小于 2 个元素,这将给出一个令人困惑的错误消息。
    • 在他确定列表至少有 2 个元素长之后,我打算让他使用它。
    • 但是你如何做到这一点而不像 length 函数那样遍历列表的长度(增加无用的开销)?
    • 这很好。当然,我不是这方面的专家,但它似乎是获取第二个元素的最简单方法就是使用运算符来获取第二个元素。
    • 确实如此。这绝对是最简单的(一行而不是其他解决方案中的两三个)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2019-01-11
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多