use*_*712 0 haskell pattern-matching parse-error
我在haskell中有以下两个函数:
plusList :: [[Int]] -> [Int]
plusList [xs ys] = add xs + plusList [ys]
plusList [[]] = 0
add::[Int] -> Int
add (x:xs) = x + add xs
add [] = 0
Run Code Online (Sandbox Code Playgroud)
所以,我认为我在plusList [xs ys] =添加xs + plusList ys中有错误
我的想法是通过设置集合,即[[Int]],通过取第一个List xs,在其上应用"add",然后用"plusList ys"递归调用第二个列表ys
我是哈斯克尔的新手,我可以这样做吗?如果不是,为什么?
bhe*_*ilr 10
你当然可以在Haskell中做你想做的事,但你的语法错了.你的add功能是正确的,但plusList事实并非如此.特别是,语法[xs ys]没有意义作为Haskell的模式,你可能想要
plusList (xs:ys) = add xs + plusList ys
Run Code Online (Sandbox Code Playgroud)
请注意这与完全相同的模式add?虽然,根据您的类型签名,很难说出您想要的是什么.类型说返回一个列表Int,但是你的函数体说只返回一个Int.如果你想要前者,你可以实现它
plusList (xs:ys) = add xs : plusList ys
Run Code Online (Sandbox Code Playgroud)
但这正是map add!如果您想要后者,请使用上面的第一个片段.
你遇到的第二个问题是
plusList [[]] = 0
Run Code Online (Sandbox Code Playgroud)
这是一个完全有效且合法的Haskell代码行,但它不会做你想要的.你看,[] :: [[Int]]和之间有区别[[]] :: [[Int]].第一个是Ints 列表的空列表,第二个是包含空列表Ints的列表.如果你跑length ([] :: [[Int]]),你会得到0,但length ([[]] :: [[Int]])你得到1!相反,只是做
plusList [] = 0
Run Code Online (Sandbox Code Playgroud)
再次,这与模式完全一样add.如果你想要plusList返回[Int],这条线应该是
plusList [] = []
Run Code Online (Sandbox Code Playgroud)
所以我们有两个版本
plusList :: [[Int]] -> Int
plusList (xs:ys) = add xs + plusList ys
plusList [] = 0
Run Code Online (Sandbox Code Playgroud)
和
plusList :: [[Int]] -> [Int]
plusList (xs:ys) = add xs : plusList ys
plusList [] = []
-- or just
-- plusList xs = map add xs
Run Code Online (Sandbox Code Playgroud)
但是,有一种更简单的方法可以做到这一点.首先,add它只是内置sum函数,但专门用于Ints.但是,由于内置使用,内置sum效率不高foldl.相反,您可以实现更快的变体
add :: [Int] -> [Int]
add xs = foldr (+) 0 xs
Run Code Online (Sandbox Code Playgroud)
该foldr和foldl功能概括那种你已经使用递归的,因为它是在函数式编程这样一个共同的模式.您可以提供将下一个值和累加器组合在一起的函数,初始累加器值和要累积的值,而不是对整个列表进行操作.在您的情况下,累加器与您的值具有相同的类型,这是很常见的.foldl和之间的区别foldr是微妙的,它们的实现看起来非常相似,但Haskell的懒惰意味着foldl可能有空间泄漏和效率问题(有很多解释为什么,当你到达那里时查找它).
此外,如果要对列表列表求和,可以使用更高阶的函数来完成
plusList = add . map add
Run Code Online (Sandbox Code Playgroud)
不需要额外的东西,没有匹配的模式,更不用说出错的语法.
| 归档时间: |
|
| 查看次数: |
106 次 |
| 最近记录: |