通过递归Haskell查找数组的第二个元素

通过递归Haskell查找数组的第二个元素,haskell,Haskell,我编写了以下代码,返回列表的第二个元素 first :: [Int] -> Int first []= 0 first [x] =x first (x:x1:xs) = x1 它工作得很好,但我希望它通过递归,例如,我继

我编写了以下代码,返回列表的第二个元素

first :: [Int] -> Int
first []= 0                                                                                                                                        
first [x] =x
first (x:x1:xs) = x1
它工作得很好,但我希望它通过递归,例如,我继续递归列表,只要它达到第二个数字,它就会给出我们的第二个数字


非常感谢。

这不是递归的“自然”案例,但如果你绝对想要递归,你可以写这个

first :: [Int] -> Int
first []= 0                                                                                                                                        
first [x] =x
first (x:x1:xs) = first [x1]

不是递归的«自然»案例,但如果你绝对想要递归,你可以写这个

first :: [Int] -> Int
first []= 0                                                                                                                                        
first [x] =x
first (x:x1:xs) = first [x1]

好问题!通过递归实现这一点的典型方法是使用以下命令:将您的函数转换为一个围绕递归函数的薄包装,并使用一个额外的参数(通常称为
go
):

但是,Haskell使用curry,因此
first
的定义可以稍微简化为
first=go 0

我建议的另一个更改是使用前奏曲中的
Maybe
类型:

data Maybe a = Just a | Nothing
也就是说,类型为
Maybe Int
的值可以是包含
Int
Just
值,也可以是不包含
Int
Nothing
值。通常,这种类型用于计算可能成功或失败的情况,例如此函数!因此,现在可以将其更改为以下内容:

first :: [Int] -> Maybe Int
first = go 0
  where
    go        1 (x:_)  = Just x     -- returning the second value
    go curIndex (x:xs) = go (curIndex+1) xs
    go        _ []     = Nothing    -- returning Nothing if it doesn't exist
现在我们可以更改类型,使其更通用(并将名称
curIndex
缩短一点),以给出最终的递归答案。我还将名称更改为
second
,因为该名称更好地反映了函数的用途(毕竟,您得到了第二个元素):


好问题!通过递归实现这一点的典型方法是使用以下命令:将您的函数转换为一个围绕递归函数的薄包装,并使用一个额外的参数(通常称为
go
):

但是,Haskell使用curry,因此
first
的定义可以稍微简化为
first=go 0

我建议的另一个更改是使用前奏曲中的
Maybe
类型:

data Maybe a = Just a | Nothing
也就是说,类型为
Maybe Int
的值可以是包含
Int
Just
值,也可以是不包含
Int
Nothing
值。通常,这种类型用于计算可能成功或失败的情况,例如此函数!因此,现在可以将其更改为以下内容:

first :: [Int] -> Maybe Int
first = go 0
  where
    go        1 (x:_)  = Just x     -- returning the second value
    go curIndex (x:xs) = go (curIndex+1) xs
    go        _ []     = Nothing    -- returning Nothing if it doesn't exist
现在我们可以更改类型,使其更通用(并将名称
curIndex
缩短一点),以给出最终的递归答案。我还将名称更改为
second
,因为该名称更好地反映了函数的用途(毕竟,您得到了第二个元素):



好吧,酷,你已经告诉我们你想做什么了。是什么阻止了您这样做,我们可以提供帮助?
listitem n ls=如果n==1,那么head ls else listitem(n-1)(tail ls)
将从列表中生成任何项目,如
listitem 2[3,6,9,12]
生成6创建一个函数,仅获取第二个项目
get2nd=listitem 2
然后
get2nd“abcdef”
产生
'b'
好吧,酷,你已经告诉我们你想做什么了。是什么阻止了您这样做,我们可以提供帮助?
listitem n ls=如果n==1,那么head ls else listitem(n-1)(tail ls)
将从列表中生成任何项目,如
listitem 2[3,6,9,12]
生成6创建一个函数,仅获取第二个项目
get2nd=listitem 2
然后
get2nd“abcdef”
产生
'b'
first[]=first[0,0];第一[x]=第一[x,x];第一[x,y]=y;first(x:y:z:xs)=first(x:y:xs)
@jorgadriano也许不用说,但是在一个长列表上,这会非常慢,因为在你最终得到一个大小为2的列表之前,你需要
n-2
递归调用。@chepner我知道:)只是开玩笑,我的意思是,首先进行这个递归是没有意义的,所以至少要使它成为O(n)列表长度感觉更像是“真正的递归”,而不是O(1)。但对无限列表不起作用。bradm的答案是一个非常好的递归函数(好的,corecursive,但它可以是递归的)。@godot没有,但它可以用最小的努力将其推广到除2以外的任意
n
first[]=first[0,0];第一[x]=第一[x,x];第一[x,y]=y;first(x:y:z:xs)=first(x:y:xs)
@jorgadriano也许不用说,但是在一个长列表上,这会非常慢,因为在你最终得到一个大小为2的列表之前,你需要
n-2
递归调用。@chepner我知道:)只是开玩笑,我的意思是,首先进行这个递归是没有意义的,所以至少要使它成为O(n)列表长度感觉更像是“真正的递归”,而不是O(1)。但是对于无限列表不起作用。bradm的答案是一个非常好的递归函数(好的,corecursive,但它可以是递归的)。@godot没有,但它可以用最小的努力将其推广到任意的
n
,而不是
go 2[]=Nothing
;我认为这使案例分析变得详尽无遗。另外,
go 1(x:)=Just x
@chepner关于详尽案例分析的观点很好-我将在中编辑它。另外,对于
go 1(x:)
,通常我会这样做,但问题特别是关于递归的,所以我想我会以递归的方式来做-注意
I
会一直增加,直到它达到
2
,在这一点上它返回当前元素。但是,由于从0开始,当您到达
go 2
时,您已经丢弃了两个元素,
x
将绑定到第三个元素<代码>go 0“abc”==go 1“bc”==go 2“c”==“c”。那些应该有
go[]=Nothing
,而不是
go 2[]=Nothing
;我认为这使得案例分析详尽无遗。而且,
go 1(x:)=Just x
@chepner关于详尽案例分析的观点很好-我