从数组中获取值

时间:2017-02-05 20:00:20

标签: list haskell

我对Haskell来说非常新,我在做一些功课时遇到了麻烦。我不明白如何正确地接收数组,并使用其中的数据。

例如在java中我会有类似

的东西
int[] arr = {...};
arr[0];
arr[1];

在我的Haskell问题中,我有

dot :: [Float] -> [Float] -> Float
-- enter code here

我找不到使用float数组内部数据的方法。我的教授这个问题的例子使用了Vectors,但是我们必须使用[Float]

我不是要求任何人解决问题,只是解释如何使用数组。

1 个答案:

答案 0 :(得分:11)

从技术上讲,这是不是数组,而是(链接)列表。这是不同的东西。列表定义为:

data [a] = [] | (a:[a])

所以它是一个有两个构造函数的数据类型:

  • 空列表[],用于表示列表的结尾;和
  • 包含两个元素的consa(项目)和尾部引用([a])。

现在我们知道您可以使用模式匹配来提取元素(并进行测试)。例如,在以下函数中:

head :: [a] -> a
head (x:_) = x

此处head期望看到cons构造,并且提取头部(第一个节点的元素)并返回该构造。或者例如:

second :: [a] -> a
second (_:(x:_)) = x

这里再次使用模式匹配来提取第二个元素。

获取元素的另一种方法是使用(!!) :: [a] -> Int -> a。运营商。您可以使用:

获取 i -th元素(从零开始)
list!!i

在语义上等同于Java中的list[i]。但请注意 - 如前所述 - 这些是链接列表,因此获取 i -th元素需要 O(i)计算工作。虽然这可能看起来像一个细节,但是当你想要获取具有大索引的对象时它会变得有点戏剧性。此外,由于(!!)被调用,你不太确定是否存在这样的元素:你没有那么多保证列表确实足够长。因此,明智的做法是使用模式匹配并寻找利用链表数据结构的巧妙方法。

对于点积的示例,您可以首先使用模式匹配,如:

dot (x:xs) (y:ys) = ...

因此您从列表中提取了 head xy。然后你可以将它们相乘并将它们添加到列表其余部分的点积中:

dot (x:xs) (y:ys) = x*y + dot xs ys

现在你只需要定义基本情况,例如:

dot [] [] = 0.0

所以把它们放在一起:

dot :: [Float] -> [Float] -> Float
dot [] [] = 0.0
dot (x:xs) (y:ys) = x*y + dot xs ys