通过递归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关于详尽案例分析的观点很好-我