我需要获取列表中的元素并将它们放入haskell中的两个单独的奇数和平均列表中。这是我到目前为止所拥有的。
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([] , [])
classEvenOdd (x:xs) = (even [xs] | odd [xs])
错误如下:
ERROR "new_1.hs":62 - Type error in explicitly typed binding
*** Term : classEvenOdd
*** Type : [Int] -> [a]
*** Does not match : [Int] -> ([Int],[Int])
答案 0 :(得分:1)
你得到的错误源于这一行:
classEvenOdd [] = []
此片段属于
类型classEvenOdd :: [a] -> [a]
这不是您所声明的类型(classEvenOdd :: [Int] -> ([Int],[Int])
)。通过将类型更改为:
classEvenOdd [] = ([], [])
。
但是,即使此问题已解决,代码中也会出现其他错误。您没有将x
值保留在列表的头部,因此一旦解决了任何语法问题(因为后面的代码片段中的语法对我来说不熟悉),您将始终以空列表结束!
您应该保留部分结果并在检查输入列表的每个元素时继续传递,或者您应该假设完成子列表xs
,然后将结果添加到正确的元素元组。
第二种方法如下:
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([], [])
classEvenOdd (x:xs) = let (evens, odds) = classEvenOdd xs in if even x
then (x:evens, odds)
else (evens, x:odds)
然而,由于依赖于每个阶段的完成值,这种方法会泄漏空间(至少没有开启优化)。
更好的方法是将部分结果作为额外参数:
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([], [])
classEvenOdd x = go ([], []) x
where go (e,o) (x:xs) = if even x
then go xs (x:e, o)
else go xs (e, x:o)
go (e,o) [] = (e, o)
答案 1 :(得分:1)
我不太确定您的代码是如何工作的,但我会通过我的方法来完成这项功能。当我想到它时,我想到了这样做:
classEvenOdd :: [Int] -> ([Int],[Int])
classEvenOdd xs = (filter odd xs, filter even xs)
但是这需要将列表过滤两次,从而使执行*所需的时间加倍。因此,我们希望在列表上定义一个函数,将其分类到两个列表中。这听起来像我们想要一个Eithers列表([Either Int Int]
)。然后可以使用partitionEithers()将列表转换为元组(([Int],[Int])
)。
import Data.Either
classEvenOdd' :: [Int] -> ([Int],[Int])
classEvenOdd' xs = partitionEithers (map eitherEvenOdd xs)
eitherEvenOdd :: Int -> Either Int Int
eitherEvenOdd i
| even i = Right i
| odd i = Left i
这也可以point free
完成import Data.Either
classEvenOdd' :: [Int] -> ([Int],[Int])
classEvenOdd' = partitionEithers.(map eitherEvenOdd)
eitherEvenOdd :: Int -> Either Int Int
eitherEvenOdd i
| even i = Right i
| odd i = Left i
*受非严格性的影响