我对Haskell来说非常新,我在做一些功课时遇到了麻烦。我不明白如何正确地接收数组,并使用其中的数据。
例如在java中我会有类似
的东西int[] arr = {...};
arr[0];
arr[1];
在我的Haskell问题中,我有
dot :: [Float] -> [Float] -> Float
-- enter code here
我找不到使用float数组内部数据的方法。我的教授这个问题的例子使用了Vectors,但是我们必须使用[Float]
我不是要求任何人解决问题,只是解释如何使用数组。
答案 0 :(得分:11)
从技术上讲,这是不是数组,而是(链接)列表。这是不同的东西。列表定义为:
data [a] = [] | (a:[a])
所以它是一个有两个构造函数的数据类型:
[]
,用于表示列表的结尾;和cons
:a
(项目)和尾部引用([a]
)。现在我们知道您可以使用模式匹配来提取元素(并进行测试)。例如,在以下函数中:
head :: [a] -> a
head (x:_) = x
此处head
期望看到cons
构造,并且提取头部(第一个节点的元素)并返回该构造。或者例如:
second :: [a] -> a
second (_:(x:_)) = x
这里再次使用模式匹配来提取第二个元素。
获取元素的另一种方法是使用(!!) :: [a] -> Int -> a
。运营商。您可以使用:
list!!i
在语义上等同于Java中的list[i]
。但请注意 - 如前所述 - 这些是链接列表,因此获取 i -th元素需要 O(i)计算工作。虽然这可能看起来像一个细节,但是当你想要获取具有大索引的对象时它会变得有点戏剧性。此外,由于(!!)
被调用,你不太确定是否存在这样的元素:你没有那么多保证列表确实足够长。因此,明智的做法是使用模式匹配并寻找利用链表数据结构的巧妙方法。
对于点积的示例,您可以首先使用模式匹配,如:
dot (x:xs) (y:ys) = ...
因此您从列表中提取了 head x
和y
。然后你可以将它们相乘并将它们添加到列表其余部分的点积中:
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