【问题标题】:F# extended Euclidian algorithm with Continuations question带有延续问题的 F# 扩展欧几里得算法
【发布时间】:2020-05-14 06:34:09
【问题描述】:

我是 F# 的新手,从本科开始就没有做过函数式编程,但我一直在尝试自学。我写了一个朴素的递归扩展欧几里得实现,它工作得很好,现在我再次尝试,但有延续。

我用一个小例子手动浏览了两次代码并得到了正确的答案,但是当我通过解释器运行它时,我没有得到相同的结果,所以我显然误解了我正在尝试做的事情。

我手动运行了 eea 7 3,我计算的(正确)结果是 (1, 1, -2)

但是当我在解释器中运行它时,我得到了

eea 7 3;;
val it : int * int * int = (1, 0, 1)

这是我的实现:

let eea a b = 
    let rec contEEA a b f = 
        match b with
        | 0 -> f () (a,1,0)
        | _ -> 
            contEEA b (a%b) (fun () t ->
                let (d,x',y') = t
                (d, y', x'-(y'*(a/b)))
            )
    contEEA a b (fun () t -> t)

直接来自教科书的幼稚方法供参考

let rec eea_gcd a b =
    match b with
    | 0 -> (a, 1, 0)
    | _ -> 
        let d, x', y' = eea_gcd b (a % b)
        (d, y', x'-(y'*(a/b)))

【问题讨论】:

    标签: functional-programming f# continuations


    【解决方案1】:

    您的基于延续的版本总是只进行一次迭代(最后一次)。当您进行递归调用时,您的延续只是直接返回结果,而不是通过传递给前一个延续将其“返回”到前一个调用。

    所以调用顺序是这样的:

    1. eea 7 3
    2. contEEA 7 3 (fun () t -> t)
    3. b <> 0 ==> 第二种情况匹配
    4. contEEA 3 1 (fun () t -> ... (d, y', ...))
    5. b <> 0 ==> 第二种情况匹配
    6. contEEA 1 0 (fun () t -> ... (d, y', ...))
    7. b = 0 ==> 第一个案例匹配
    8. 继续调用f () (1, 1, 0)
    9. 继续计算结果(1, 0, 1 - (0*(3/1)) = (1, 0, 1)并立即返回

    想要做的是,当第一个延续计算 (1, 0, 1) 的结果时,它应该将它传递给 previous 延续,以便它可以继续从那里开始计算,最终将结果传递给第一个延续 fun () t -> t,后者将其返回给消费者。

    为此,请替换此行:

    (d, y', x'-(y'*(a/b)))
    

    有了这个:

    f (d, y', x'-(y'*(a/b)))
    

    另外,关于其他方面的几点说明。

    1. 延续的第一个参数(单位,())不是必需的,因为它从未实际使用过(怎么可能?)。你可能会失去它。

    2. 去掉unit参数后,第一个延续变成fun t -> t,有一个特殊的名字id(又名“恒等函数”)

    3. 与其用let 解构三元组,不如直接在参数声明中进行。参数可以是模式!

    应用以上所有内容,以及实际的问题修复,这里有一个更好的版本:

    let eea a b = 
        let rec contEEA a b f = 
            match b with
            | 0 -> f (a,1,0)
            | _ -> 
                contEEA b (a%b) (fun (d,x',y') -> 
                    f (d, y', x'-(y'*(a/b)))
                )
        contEEA a b id
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      相关资源
      最近更新 更多