如何逐个元素遍历列表

问题描述

我刚刚开始学习 Haskell,我正在尝试编写一些基本函数,以便更好地理解这种语言。

我想编写一个函数,它接受一个列表和一个 Int (N) 作为参数并返回列表中索引 N 处的元素,而不使用 {{1 }} 运算符或任何内置函数

这是我尝试过的:

!!

它可以工作,但它向右移动了。例如,myHead :: [a] -> a myHead (x:_) = x myHead [] = error "head: empty list" myNth :: [a] -> Int -> a myNth x i = if i < 0 then error "nth: index can't be negative" else myNthIterator x i 0 myNthIterator :: [a] -> Int -> Int -> a myNthIterator [] i n = error "nth: bad index" myNthIterator (_:x) i n = if i == n then myHead x else myNthIterator x i ( n + 1 ) 会给出 myNth [1,2,3,4] 2 而不是 4

据我所知,3 删除了列表的第一个元素,我不知道如何逐个元素地遍历列表。

有人可以让我走上这条路吗?我发现很难为初学者找到这种语言的资源。

解决方法

我们可以使用 Maybe 来模拟索引是否有效。

nth :: Int -> [a] -> Maybe a
nth 0 (x : _) = Just x
nth n (x : xs) = nth (n - 1) xs
nth _ [] = Nothing

我们可以在索引上进行模式匹配以获得我们的基本情况,并在列表上获得第一个元素和尾部。

,

你在那里用 (_:x) 做什么被称为 “模式匹配”,以防你不知道。遍历列表的一般模式是 (x : xs),其中 x 是匹配列表的头元素,xs 是列表的其余部分。如果您使用 _,则不会删除任何内容,它仍然与 _ 匹配,这是说“我不会使用这个”的约定。

有了它,您可以制作这样的功能:

myNth :: [a] -> Int -> a
myNth  []      _ = error "out of range"
myNth (x : xs) 0 = x
myNth (_ : xs) n = myNth xs (n - 1)

每当调用 myNth 时,它都会从上到下遍历那些试图将模式与输入匹配的定义。因此,当您调用 myNth [10,11] 1 时,它不会匹配第一个子句,因为 [10,11] 不匹配空列表,它也不会匹配第二个子句,因为 1 不是 {{1 }} ,因此它将匹配第三种情况,它将匹配 0 上的 [10,11],因此 (10 : [11])_10 是 {{1} } 和 xs 将匹配为 [11]。然后它递归地调用自己,如1。现在 that 将匹配第二种情况,并且它会从 n

上的 myNth [11] 0 匹配返回 x

就像 414owen 说的,您可以使用 [11] 类型来避免使用 (11 : [])

PS:我不知道你有多初学者,但我假设你知道 Maybe a 运算符,它将元素添加到列表中......如果你更深入(afaik)每个列表都是实际上存储为 error 的序列,相当于 :,相当于 a:(b:(c:(d:(e:[])))) 等。

,

它可以工作,但它向右移动了。例如,myNth [1,2,3,4] 2 会给出 4 而不是 3

myNthIterator (_:x) i n = if i == n
  then myHead x
  else myNthIterator x i ( n + 1 )

让我们看看myNthIterator [1..4] 1 1

myNthIterator [1..4] 1 1            -- replace [a,b] with (a: (b : []))
== myNthIterator (1 : [2,4]) 1 1
-- matching with `myNthIterator (_:x) i n` will result in
-- 1 ~ _
-- x ~ [2,4]
-- i ~ 1
-- n ~ 1
== if 1 == 1 then myHead [2,4] else myNthIterator [2,4] 1 (1 + 1)
== myHead [2,4]
== 2

因此 (_:x)(1 : [2,4]) 的匹配是可疑的。修复它的第一步是将 (_:x) 替换为 (x:xs)

myNthIterator (x:xs) i n = ...

在我们的示例中,这意味着 x == 1xs == [2,4]