我对 Haskell 非常陌生,而且我在做一些家庭作业时遇到了麻烦。我不明白如何正确地接受一个数组,并在其中使用数据。
例如在java中我会有类似的东西
int[] arr = {...};
arr[0];
arr[1];
在我的 Haskell 问题中我有
dot :: [Float] -> [Float] -> Float
-- enter code here
我找不到使用 float 组中数据的方法。我的教授针对此问题的示例使用了 Vectors,但我们必须使用 [Float]
我不是要任何人做这道题,只是解释一下如何使用数组。
最佳答案
从技术上讲,这不是数组,而是(链接)列表。那是不同的东西。列表定义为:
data [a] = [] | (a:[a])
所以它是一个有两个构造函数的数据类型:
- 空列表
[]
,用于表示列表结束;和 cons
具有两个元素:a
(项目)和对尾部的引用 (a[a]
)。
现在我们知道您可以使用模式 匹配来提取元素(并进行测试)。例如在下面的函数中:
head :: [a] -> a
head (x:_) = x
这里 head
期望看到一个 cons
构造,它提取 head(第一个节点的元素)并返回它。或者例如:
second :: [a] -> a
second (_:(x:_)) = x
这里您再次使用模式匹配来提取第二个元素。
另一种获取元素的方法是使用 (!!) :: [a] -> Int -> a
.运算符(operator)。您可以获得第 i 个元素(从零开始),方法是:
list!!i
在语义上等同于 Java 中的 list[i]
。但是请注意 - 如前所述 - 这些是链表,因此获得第 i 个元素需要 O(i) 计算量。虽然这看起来像是一个细节,但当您想要获取具有大索引的对象时,它可能会变得有点戏剧化。此外,由于 (!!)
被调用,您不太确定是否存在这样的元素:您没有太多保证列表确实足够长。因此,明智的做法是使用模式匹配并寻找巧妙的方法来利用链表数据结构。
对于点积的示例,您可以首先使用模式匹配,例如:
dot (x:xs) (y:ys) = ...
因此您已经从列表中提取了heads 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
关于list - 从数组中获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42056615/