也许是将null附加到列表的替代方法

时间:2018-04-04 21:05:57

标签: list haskell

我试图从列表中仅提取奇数位置的元素。我知道Data.List中有特定的方法,但我是新的,我正在尝试通过重新发明轮子来学习。

到目前为止,我已尝试过这种方法,我正在分支内部方法

manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where 
        go [] nl _ = nl
        go (x:xs) rez cnt=if cnt `mod`2 ==0 then go xs (x:rez) (cnt+1) else go xs rez (cnt+1)

但我必须在结束时扭转这一结果。

有没有更多的原子然后使用也许来处理null的

因此,如果我移动cons运算符左侧的 if子句,我可以返回什么而不是null?我已经尝试了Nothing,[]没有成功。

manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where 
        go [] nl _ = nl
        go (x:xs) rez cnt=if cnt `mod`2 ==0 then x else *(something?!)* : go xs rez (cnt+1)

2 个答案:

答案 0 :(得分:7)

  

但我必须在结束时扭转这一结果。

如果您使用累加器,就像在这里一样,是的,您必须反转结果。如果你正在处理一个"无限列表",这也会导致一个问题,因为在这种情况下,递归永远不会终止,因此你会陷入无限循环(直到你的内存耗尽)。

  

所以,如果我在cons运算符的左侧移动if子句,我可以返回什么而不是null?

实际上并不是null(有undefined,但是我们会将这个值添加到头部),Nothing也不会这样做,因为那是一个Maybe类型的数据构造函数。你可以使用空列表,以防你想要终止序列,但你不能填写一些"空"在头脑中。

但实际上你不需要内部方法,也不需要对指数进行评估。您可以使用 pattern 匹配:

manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF [x] = [x]
manF [] = []

请注意,这里的模式是(x:_:xs),它是(x:(_:xs))的紧凑形式,因此我们在这里匹配" cons"以x为头,尾巴应该是" cons"还有头_(我们不关心的值),以及尾xs。通过这样做,我们开发了一种方法,可以在遍历列表时进行两次跳跃。

其他子句是基本情况:对于单例列表,我们返回该单例列表,对于空列表,我们返回空列表。我们可以将最后两个合并为一个子句,如:

manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF l = l

请注意,由于懒惰,如果我们处理一个"无限列表",算法将不会陷入无限循环(当然,鉴于源列表的生成器不会进入无限循环),因此我们可以用它来处理"流"。

另一个优点是我们的整数永远不会遇到溢出(尽管对于偶数奇怪的检查不会产生影响,对于稍微不同的函数,例如每个第三个​​元素的产生,这个可能导致问题。)

答案 1 :(得分:6)

尝试相互递归。对此的标准演示是相互实施oddeven

odd, even :: Int -> Bool
odd 0 = False
odd n = not (even (n - 1))
even 0 = True
even n = not (odd (n - 1))

对于manF,您可以写

manF :: [Int] -> [Int]
manF = go_odd  where 
    go_odd [] = []
    go_odd (x:xs)  = x : go_even xs
    go_even [] = []
    go_even (x:xs) = go_odd xs