对新创建的数据进行操作(更新阵列)

时间:2017-05-17 11:44:06

标签: haskell functional-programming

我创建了以下数据类型。

Array_

现在,我想创建一个更新函数 - 给定索引,update :: ( Int, Array_ a, a ) -> Array_ a 和新值 - 更新给定索引处的数组值。

这是函数的签名......

update :: ( Int, Array_ a, a ) -> Array_ a
update( i, A[], new_value ) = error( ( show i ) ++ " is not an index" )
update( i, A( ( j, Just_ x ):l ), new_value )
    | i == j = A( ( j, Just_ new_value ):l )
    | i /= j = update ( i, A l, new_value )

......这是完整的功能

++

问题出现在函数的最后一行。 这是对列表末尾的递归调用,但它不保留以前考虑的数组元素。

我正考虑使用:运算符或... i /= j = ( j, Just_ x ):update ( i, A l, new_value )运算符,但两次都出错。

... i /= j = A[( j, Just_ x )] ++ update ( i, A l, new_value )

var arr1 = [CustomObject]() var arr2 = [CustomObject]() var arr3 = [CustomObject]() var arr4 = [CustomObject]() self.arr3 = self.arr1 + self.arr2 //concatenate two arrays self.arr4 = Array(Set(arr3)) // find out uniq values // below is the extension extension Array where Element : Hashable { var unique: [Element] { var uniqueValues: [Element] = [] forEach { item in if !uniqueValues.contains(item) { uniqueValues += [item] } } return uniqueValues } }

我该如何区别对待?

1 个答案:

答案 0 :(得分:3)

首先,它有点 un-Haskell 与元组一起使用,通常你定义单独的参数,如:

update :: Int -> Array_ a -> a -> Array_ a

这样您就可以轻松使用update 5函数,稍后您将提供其他参数。

然而问题在于你的最后一个分支:

| i /= j = update i (A l) new_value

因此执行递归调用,但递归调用的结果将是 final 结果。为了解决此问题,您只需添加您检查的项目,并且与索引不匹配。由于您对所有索引失败执行此操作,因此所有不匹配的索引将位于最终结果中,因此:

| i /= j = (j, Just_ x) : update i (A l) new_value.

现在我们获得:

update :: Int -> Array_ a -> a -> Array_ a
update i (A []) new_value = error( ( show i ) ++ " is not an index" )
update i (A ((j, Just_ x):l)) new_value
    | i == j = A ((j, Just_ new_value):l)
    | i /= j = let A t = update i (A l) new_value in A ((j, Just_ x):t)

话虽如此,我们仍然可以采取一些措施来改善我们的职能:

  • 我们不考虑的变量通常用通配符写成,
  • 我们可以使用别名 @来阻止我们重新打包列表的头部。
  • 由于您使用==/=,编译器可能会出错。最好使用otherwise(最后一个分支中的True别名(这与Java中的else或多或少相同)。
  • 您可以使用hlint获得一些额外的美化。

如果我们考虑上述评论,我认为 - 更优雅的功能将是:

update :: Int -> Array_ a -> a -> Array_ a
update i (A []) _ = error $ show i ++ " is not an index"
update i (A (h@(j,Just_):l)) new_value
    | i == j = A ((j, Just_ new_value):l)
    | otherwise = let A t = update i (A l) new_value in A (h:t)

最后还有一个案例尚未解决:如果列表中有Nothing_,该怎么办?如果您不关心该值是Just_ x还是Nothing_,则可以将其重写为:

update :: Int -> Array_ a -> a -> Array_ a
update i (A []) _ = error $ show i ++ " is not an index"
update i (A (h@(j,_):l)) new_value
    | i == j = A ((j, Just_ new_value):l)
    | otherwise = let A t = update i (A l) new_value in A (h:t)