F# 中的递归 lambda

发布于 2024-07-21 21:17:37 字数 871 浏览 7 评论 0原文

以这个示例代码为例(暂时忽略它,它的效率非常低)

let listToString (lst:list<'a>) = ;;' prettify fix

    let rec inner (lst:list<'a>) buffer = ;;' prettify fix
        match List.length lst with 
        | 0 -> buffer
        | _ -> inner (List.tl  lst) (buffer + ((List.hd lst).ToString()))

    inner lst ""

这是我在 F# 中不断遇到的常见模式,我需要一个内部函数,它可以在某个值上递归自身 - 而且我只需要这个函数一次,是吗?以任何可能的方式从其自身内部调用 lambda(某些魔术关键字或其他东西)? 我希望代码看起来像这样:

let listToString2 (lst:list<'a>) = ;;' prettify fix

    ( fun 
        (lst:list<'a>) buffer -> match List.length lst with ;;' prettify fix
                                 | 0 -> buffer
                                 | _ -> ##RECURSE## (List.tl lst) (buffer + ((List.hd lst).ToString())) 
    ) lst "" 

但正如您可能期望的那样,无法引用其内部的匿名函数,这是我放置 ##RECURSE## 的地方所需要的

Take this example code (ignore it being horribly inefficient for the moment)

let listToString (lst:list<'a>) = ;;' prettify fix

    let rec inner (lst:list<'a>) buffer = ;;' prettify fix
        match List.length lst with 
        | 0 -> buffer
        | _ -> inner (List.tl  lst) (buffer + ((List.hd lst).ToString()))

    inner lst ""

This is a common pattern I keep coming across in F#, I need to have an inner function who recurses itself over some value - and I only need this function once, is there in any way possible to call a lambda from within it self (some magic keyword or something) ? I would like the code to look something like this:

let listToString2 (lst:list<'a>) = ;;' prettify fix

    ( fun 
        (lst:list<'a>) buffer -> match List.length lst with ;;' prettify fix
                                 | 0 -> buffer
                                 | _ -> ##RECURSE## (List.tl lst) (buffer + ((List.hd lst).ToString())) 
    ) lst "" 

But as you might expect there is no way to refer to the anonymous function within itself, which is needed where I put ##RECURSE##

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

送你一个梦 2024-07-28 21:17:37

是的,可以使用所谓的 y-combinators (或 定点组合器)。 例如:

let rec fix f x = f (fix f) x

let fact f = function
 | 0 -> 1
 | x -> x * f (x-1)


let _ = (fix fact) 5 (* evaluates to "120" *)

我不知道 F# 的文章,但这个 haskell 条目 可能也会有帮助。

但是:如果有任何替代方案,我不会使用它们 - 它们很难理解。

您的代码(此处省略类型注释)是标准构造,并且更具表现力。

let listToString lst =

    let rec loop acc = function
        | []    -> acc
        | x::xs -> loop (acc ^ (string x)) xs

    loop "" lst

Yes, it's possible using so called y-combinators (or fixed-point combinators). Ex:

let rec fix f x = f (fix f) x

let fact f = function
 | 0 -> 1
 | x -> x * f (x-1)


let _ = (fix fact) 5 (* evaluates to "120" *)

I don't know articles for F# but this haskell entry might also be helpful.

But: I wouldn't use them if there is any alternative - They're quite hard to understand.

Your code (omit the type annotations here) is a standard construct and much more expressive.

let listToString lst =

    let rec loop acc = function
        | []    -> acc
        | x::xs -> loop (acc ^ (string x)) xs

    loop "" lst
一直在等你来 2024-07-28 21:17:37

请注意,虽然您说您只使用该函数一次,但从技术上讲,您通过名称引用它两次,这就是为什么给它命名是有意义的。

Note that although you say you use the function only once, technically you refer to it by name twice, which is why it makes sense to give it a name.

伪心 2024-07-28 21:17:37

我提交了一份语言建议来解决这个问题。 请投票支持它。

使用 fun rec 开始递归 lambda

I submitted a language suggestion to solve this problem. Please vote for it.

Use fun rec to begin a recursive lambda

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文