【问题标题】:match error in haskellhaskell中的匹配错误
【发布时间】:2014-03-18 13:41:05
【问题描述】:

我在 haskell 中有以下代码,我得到了

  1. 无法将类型 [Int] 与 `Bool' 匹配
  2. 无法匹配类型[[a0]] -> [a0]' with[Int]' 预期类型:[Int] -> [Int] 实际类型:[Int] -> [[a0]] -> [a0]

代码:

findlist:: [[Int]] -> [Int] 
findlist (l1, l2, l3, l4, l5) = do      1)
    let n = length l1
    e1 <- [1..n]
    e2 <- [1..n]
    e3 <- [1..n]
    e4 <- [1..n]
    e5 <- [1..n]
    let list1 = pick_list $ myperms e1 l1   --here
        list2 = pick_list $ myperms e2 l2   --here
        list3 = pick_list $ myperms e3 l3   --here
        list4 = pick_list $ myperms e4 l4   --here
        list5 = pick_list $ myperms e5 l5   --here
    guard $ all (== list1) $ [list2, list3, list4, list5]
    guard $ e1 `notElem` [e2, e3, e4, e5]
    guard $ e2 `notElem` [e3, e4, e5]
    guard $ e3 `notElem` [e4, e5]
    guard $ e4 `notElem` [e5]
    return concat list1                    2)

类型签名:

pick_list:: [[Int]] -> [Int]
myperms:: Int -> [Int] -> [[Int]] 

它有什么问题,我怎么知道什么时候会出现这样的错误?提前致谢。

【问题讨论】:

  • 我没有收到您遇到的错误。如果我输入myperms :: Int -&gt; [Int] -&gt; [[Int]]; myperms = undefinedpick_list :: [[Int]] -&gt; [Int]pick_list = undefined。此外,我怀疑您是否尝试编译此确切代码,因为 findlist 采用 5 元组,而不是列表,但您显然已经给它一个类型签名,表明它需要一个列表。这是我使用此代码得到的唯一编译错误。
  • 现在可以了,但是速度很慢。我考虑过限制 e1、e2 等的范围,但我需要一个函数来删除给定列表的给定子列表。
  • 在这种情况下,它就像 e2

标签: haskell


【解决方案1】:

您的where 子句需要在findlist 下方缩进。然而,这段代码还有更多的问题。


我看到的第一个大问题是你得到了list 的特定元素,但你没有确保它至少有5 个元素。也许你应该传入一个元组?

其次,您在 where 子句中引用了elem1elem2 等,但它们不在列表理解范围之外,不能在方括号之外使用。

第三,您的理解将返回list1 的副本,在您庞大的列表理解条件下,每成功匹配一个。即使它可以编译,我认为这段代码也不会做你想做的事。


您可以改为将其写成一元形式。我还冒昧地使用Control.Monad.guard 简化了您的检查并摆脱了elements

findlist (l1, l2, l3, l4, l5) = do
    let n = length l1
    e1 <- [1..n]
    e2 <- [1..n]
    e3 <- [1..n]
    e4 <- [1..n]
    e5 <- [1..n]
    let list1 = pick_list $ myperms e1 l1
        list2 = pick_list $ myperms e2 l2
        list3 = pick_list $ myperms e3 l3
        list4 = pick_list $ myperms e4 l4
        list5 = pick_list $ myperms e5 l5
    guard $ all (== list1) [list2, list3, list4, list5]
    guard $ e1 `notElem` [e2, e3, e4, e5]
    guard $ e2 `notElem` [e3, e4, e5]
    guard $ e3 `notElem` [e4, e5]
    guard $ e4 `notElem` [e5]
    return list1

这段代码肯定更容易阅读,并且性能相当(对于大型n 来说会很慢)

【讨论】:

  • 1) 我把 where 放在 findlist 下,但仍然是同样的错误。 2) 该列表肯定有 5 个成员。它在规范中 3) 好吧,您对范围是正确的,但是 elem1, elem2 ... 用于 where 定义。也许这不算数.. 4) 只有一个 list1 符合所有条件。
  • @BillyGrande 检查我的编辑。 2) 如果您的规范说 list 有 5 个元素,请使用 5 元组。 3) 如果在 where 定义中需要 elem1 等,则必须将它们作为 lets 拉入理解,这就是 Haskell 中作用域的工作方式。 4) 在我将代码重新格式化为单子形式后,我看到您正在尝试根据所有这些条件查找特定列表。
  • 1) 忘了说 n = length(l1) 2) 不在范围内:`guard'
  • @BillyGrande 关于为什么会出现语法错误,我唯一的另一个猜测是,您以错误的方式格式化了您的理解,或者您混合了制表符和空格。我会检查,但如果没有 findlistmypermspick_list 的类型签名,我将无法编译您的代码。
  • @BillyGrande 对于guard 函数,您必须导入Control.Monad,这就是为什么我将其指定为Control.Monad.guard...
猜你喜欢
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多