【问题标题】:Parse error in pattern: xs - understanding模式中的解析错误:xs - 理解
【发布时间】:2014-07-03 03:17:54
【问题描述】:

我在haskell中有以下两个函数:

plusList :: [[Int]] -> [Int]
plusList [xs ys] = add xs + plusList [ys]
plusList [[]] = 0


add::[Int] -> Int
add (x:xs) = x + add xs
add [] = 0

所以,我认为我在 plusList [xs ys] = add xs + plusList ys 中有错误

我的想法是遍历集合的集合,即 [[Int]],通过获取第一个 List xs,对其应用“add”,然后使用“plusList ys”递归调用第二个列表 ys

我是 haskell 的新手,我可以这样做吗?如果不是,为什么?

【问题讨论】:

    标签: haskell pattern-matching parse-error


    【解决方案1】:

    你当然可以在 Haskell 中做你想做的事,但是你的语法是错误的。您的 add 函数是正确的,但 plusList 不是。特别是,[xs ys] 语法作为 Haskell 的模式毫无意义,你可能想要

    plusList (xs:ys) = add xs + plusList ys
    

    注意这与add 的模式完全相同吗?虽然,从你的类型签名很难说出你到底想要什么。类型说返回Int 的列表,但你的函数体说只返回Int。如果你想要前者,你可以实现它

    plusList (xs:ys) = add xs : plusList ys
    

    但这正是map add!如果您想要后者,请使用上面的第一个 sn-p。

    你遇到的第二个问题是

    plusList [[]] = 0
    

    这是一段完全有效且合法的 Haskell 代码行,但它不会做你想做的事。你看,[] :: [[Int]][[]] :: [[Int]] 之间是有区别的。第一个是Ints 的空列表,第二个是包含Ints 的空列表的列表。如果您运行length ([] :: [[Int]]),您将获得0,但对于length ([[]] :: [[Int]]),您将获得1!。相反,只是做

    plusList [] = 0
    

    同样,这与add 中的模式完全相同。如果您希望 plusList 改为返回 [Int],则此行应该是

    plusList [] = []
    

    所以我们有两个版本

    plusList :: [[Int]] -> Int
    plusList (xs:ys) = add xs + plusList ys
    plusList [] = 0
    

    plusList :: [[Int]] -> [Int]
    plusList (xs:ys) = add xs : plusList ys
    plusList [] = []
    -- or just
    -- plusList xs = map add xs
    

    不过,有一种更简单的方法可以做到这一点。首先,add 只是内置的sum 函数,但专门用于Ints。但是,内置的sum 由于使用foldl,因此效率不高。相反,您可以使用

    实现更快的变体
    add :: [Int] -> [Int]
    add xs = foldr (+) 0 xs
    

    foldrfoldl 函数概括了您所使用的递归类型,因为它是函数式编程中如此常见的模式。您提供了一个函数,用于将下一个值和累加器、初始累加器值和要累加的值组合在一起,而不是对整个列表进行操作。在您的情况下,累加器与您的值具有相同的类型,这很常见。 foldlfoldr 之间的区别很微妙,它们的实现看起来非常相似,但是 Haskell 的懒惰意味着 foldl 可能存在空间泄漏和效率问题(关于原因有很多解释,当你到那里)。

    另外,如果你想对一个列表求和,你可以使用简单的高阶函数来完成

    plusList = add . map add
    

    不需要任何额外的东西,没有要匹配的模式,更不用说语法错误了。

    【讨论】:

    • 我认为您混淆了foldrfoldl'foldr 这里仍然会有空间泄漏,尽管我认为只有堆栈空间而不是 thunk 构建(随后是 thunk 运行后的堆栈)。
    猜你喜欢
    • 2017-10-29
    • 2013-05-08
    • 1970-01-01
    • 2012-01-23
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2013-12-24
    相关资源
    最近更新 更多