在Haskell中重写Python数组操作函数

4

我希望尝试在Haskell中重写我的数据透视例程,但我立刻遇到了困难...

这是我原来的Python例程(我已经添加了大量注释以弥补类型缺失):

def pivot(entering, leaving, B, A, Z):
    """
    @param entering integer indicating the entering col #
    @param leaving integer indicating the leaving col #
    @param B vector/array of integers, representing the basis
    @param A matrix of floating point numbers
    @param Z vector/array of floating point numbers
    returns tuple:
        (B, A, Z) with pivoted tableau
    """

    # Copy A
    M = [row for row in A]
    # Append Z row to the matrix
    M.append(Z)

    # Find the main row
    eq_no = B.index(leaving)
    col = entering

    # Go through all other rows and do Gaussian elimination on them:
    for i in range(len(M)):
        if i == eq_no:
            continue
        # Do pivot - ignore "zero_out" function for now
        #            assume it returns a vector same size as row M[i]
        M[i] = zero_out(M[i], M[eq_no], col)

    # Reassign B's
    Bprime = [b for b in B]  # copy B
    Bprime[eq_no] = entering  # replace

    # return new B, matrix M (less 1 row), and last row of M
    return (Bprime, M[:len(M)-1], M[len(M)-1])

这是我目前的进展...

type Matrix = [ [Double] ]
type Vector = [ [Vector] ]

matrix = [ [1, 2, 3], [2, 3, 4]]
hello:: Matrix -> Int
hello m = length m

pivot:: Int -> Int -> Vector -> Matrix -> Matrix -> Matrix
pivot entering leaving b a z = 
    let m = a::z
        eq_no = elemIndex leaving b
        case eq_no of
            Just no -> no
            Nothing -> 1
        col = entering

    in  ????

我非常关注人们如何实现"矩阵"和"向量"类型,以及如何操作数组-比如替换其中的元素或矩阵中的行。

如果有不清楚的地方,请告诉我,谢谢!


3
你确定 Vector 类型是正确的吗? - phimuemue
这个链接可能会有帮助:http://www.cs.auckland.ac.nz/references/haskell/haskell-intro-html/arrays.html#sect11.5 - ДМИТРИЙ МАЛИКОВ
哈哈,不是的。我在那个时候放弃编译了 :-( - Andriy Drozdyuk
1
@dmitry.malikov 哇,看起来好神秘啊。那么多符号... - Andriy Drozdyuk
我看到的符号有:列表推导语法 [ foo | x <- gen, baz],元组语法 (foo, bar),数组索引 arr ! index,守卫语法 | predicate = expression。这些都是相当基本的 Haskell;也许可以先阅读教程的前几节,或者从 LYAH 开始。 - Dan Burton
谢谢,我已经读了LYAH的7章 - 问题不在于语法,而是在于第一次写它。我甚至不知道如何着手。还记得你第一次用新语言编写程序的感觉吗? - Andriy Drozdyuk
1个回答

2

我现在没有时间把你的代码翻译成Haskell,但是我会批评你的代码并提供一些建议。

首先,类型[Foo]表示“Foo列表”。通过“列表”,我指的是不可变的单向链表。 Matrix类型非常合理:矩阵是“行”的列表,其中“行”是Double类型的列表。然而,你的Vector类型没有意义。也许你的意思是:

type Vector = [Double]
type Matrix = [Vector]

回到一般列表。列表可以使用!!运算符进行索引。例如:

["foo", "bar", "baz"] !! 1 == "bar"

您可以在一个元素前面添加:(发音为“cons”)
"quux" : ["foo", "bar", "baz"] == ["quux", "foo", "bar", "baz"]

您可以使用++将两个列表连接起来。
[1,2] ++ [3,4] == [1,2,3,4]

因此,您可以使用 list ++ [x] 添加元素,但这种方式效率低下且不建议使用。实际上,索引也相当慢。如果需要高效的索引和添加,请改用 Data.Sequence。但作为初学者,我不建议您现在过多地关注效率。
我建议您在尝试翻译代码之前先学习一些 Haskell;您的 Python 算法使用了变异,而 Haskell 通常避免使用变异,虽然这是可能的。一旦您对 Haskell 类型和函数有了更多的经验,那么您可能会对 vector 包 感兴趣。

谢谢,感激不尽!那么如何替换数组中给定索引处的元素? - Andriy Drozdyuk
@drozzy 如果你开始替换列表中特定索引处的元素(不是数组!有区别),你很快就会后悔。 - Daniel Wagner
如果你真的想做那样的事情,请查看Data.Sequence # indexingSeq是一种纯函数数据结构,当进行这样的操作时仍然保持着相当不错的性能。如果你想要可变数组的原始性能,那么使用它们。在至少阅读LYAH之后,并且可能还要阅读RWH之前,不建议这样做。 - Dan Burton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接