List 可能的替代方法是在列表中附加null

List 可能的替代方法是在列表中附加null,list,haskell,List,Haskell,我试图从列表中只提取奇数位置的元素。我知道数据中有特定的方法。列表,但我是新手,我试图通过重新发明轮子来学习 到目前为止,我已经尝试了这种方法,我将内部方法分支 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

我试图从列表中只提取奇数位置的元素。我知道数据中有特定的方法。列表,但我是新手,我试图通过重新发明轮子来学习

到目前为止,我已经尝试了这种方法,我将内部方法分支

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)
但最终我必须扭转这一结果

还有什么比处理空值更原子的吗

因此,如果我移动
cons
操作符左侧的if子句,我可以返回什么而不是null?我什么也没试过,没有成功

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)
但最终我必须扭转这一结果


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

因此,如果我移动cons操作符左侧的if子句,我可以返回什么而不是null

实际上没有类似于
null
(有
未定义的
,但我们会将该值添加到头部),也不会有
任何东西
起作用,因为这是
可能
类型的数据构造函数。如果您想终止序列,可以使用空列表,但不能在头部填写一些“空”

但事实上,你不需要一个内在的方法,也不需要计算指数。您可以为此使用模式匹配:

manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF [x] = [x]
manF [] = []
注意,这里的模式是
(x::xs)
,它是
(x:(:xs))
的一种紧凑形式,因此这里我们将一个“cons”与
x
匹配作为头,尾应该是一个“cons”,与头
(一个我们不关心的值)以及尾
xs
。通过这样做,我们开发了一种方法,可以在遍历列表时使跳数为2

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

manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF l = l
请注意,由于懒惰,如果我们处理“无限列表”,算法将不会陷入无限循环(当然,给定源列表的生成器不会进入无限循环),因此我们可以使用它来处理“流”


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

尝试相互递归。这方面的标准演示是在相互之间实现
奇数
偶数

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

如果你像这里一样使用累加器,是的,你必须反转结果。
manF[x]=[x]
——这难道不意味着不管最后一个元素是否在列表中的奇数位置,它都会被添加吗?@andrybak:既然我们以2为跳跃,它就不会添加最后一个元素。例如,如果我们处理
manF[1,4]
,它将导致
1:manF[]
。如果我们处理一个单例列表,比如
[1]
,它确实会导致
[1]
。但这是逻辑上的,因为这是第一个元素(因此是一个奇怪的索引)。我不理解单例列表的情况。我应该在匹配的x=[x]或x=x中写入吗?我的意思是,你必须同时使用例如5->[5]和[5]>[5]?@Bercoviciarian:单例列表的模式是
(x:[])
,或者如果我们使用语法糖,我们在头部使用
[x]
x
意味着我们匹配列表,而不管它的值。@Bercovici Adrian:是的,在这种情况下我们会提取vour变量(或者在这个答案中的模式匹配中提取三个),但关键是我们从不做重复的工作,因为我们跳两个。我们提取三个值,但使用第一个值,忽略第二个值,然后在第三个值上递归。结果,递归步骤的数量减少了,而匹配(我们无论如何都要做)在全局上仍然是相同的。