有人用 F# 构建过 Lazy Monad 吗?

发布于 2024-12-25 14:47:46 字数 438 浏览 2 评论 0原文

我一直在阅读 Chris Okasaki 的纯函数式数据结构,并且想知道是否有一种好方法可以在 monad 内部使用 F# 构建惰性算法,从而实现惰性计算(Lazy monad)。 Chris 在 SML 中使用了悬浮/强制语法的自定义扩展,但我想我们可以在 F# 中使用简单的 monad。在 F# 中手动使用惰性和强制似乎相当混乱。

我在Scheme中找到了 this 实现,但我不知道它将有多么适用。

从我粗略的了解和研究来看,在合理的限度内,这似乎既可行又可取。

请告诉我 :)

I've been reading Chris Okasaki's Purely Functional Data Structures, and am wondering if there is a nice way to build lazy algorithms with F# inside of a monad that enables lazy computation (a Lazy monad). Chris used a custom extension for suspension / force syntax in SML, but I'd like to think that we could instead just use a simple monad in F#. Manual use of lazy and force in F# seems pretty cluttery.

I found this implementation in Scheme, but I don't know how applicable it would be.

From my cursory knowledge and research, it seems both feasible and desirable within reasonable limitations.

Please let me know :)

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

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

发布评论

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

评论(2

A君 2025-01-01 14:47:46

要移植 Okasaki 代码,为什么不直接使用 F# lazy 关键字和一些辅助语法来表达强制,例如:

let (!) (x: Lazy<'T>) : 'T = x.Value

由于 F# 类型系统无法正确表达 monad,我假设您建议为lazy 定义一个计算表达式计算。我想人们可以做到这一点,但这到底有什么帮助呢?

type LazyBuilder =
    | Lazy

    member this.Return(x: 'T) : Lazy<'T> =
        Lazy.CreateFromValue(x)

    member this.Bind(x: Lazy<'T1>, f: 'T1 -> Lazy<'T2>) : Lazy<'T2> =
        lazy (f x.Value).Value

let test () =
    let v =
        Lazy {
            let! x = lazy 1
            let! y = lazy 2
            return x + y
        }
    v.Value


let (!) (x: Lazy<'T>) : 'T = x.Value

let test2 () =
    let v =
        lazy
            let x = lazy 1
            let y = lazy 2
            !x + !y
    !v

To port Okasaki code, why not just go with F# lazy keyword and some helper syntax to express forcing, for example:

let (!) (x: Lazy<'T>) : 'T = x.Value

Since F# type system cannot properly express monads, I assume you suggest defining a computation expression for lazy computations. I guess one can do that, but how would that help exactly?

type LazyBuilder =
    | Lazy

    member this.Return(x: 'T) : Lazy<'T> =
        Lazy.CreateFromValue(x)

    member this.Bind(x: Lazy<'T1>, f: 'T1 -> Lazy<'T2>) : Lazy<'T2> =
        lazy (f x.Value).Value

let test () =
    let v =
        Lazy {
            let! x = lazy 1
            let! y = lazy 2
            return x + y
        }
    v.Value


let (!) (x: Lazy<'T>) : 'T = x.Value

let test2 () =
    let v =
        lazy
            let x = lazy 1
            let y = lazy 2
            !x + !y
    !v
桃气十足 2025-01-01 14:47:46

我不确定这是否有帮助,但如果您出于某种原因特别想要的话,您可以完全避免使用lazy关键字:(

type ('a, 'b) lazyT = Lz of 'a * ('a -> 'b)

let force (Lz (a, e)) = e a
let pack x = Lz(x, (fun i -> i))

type MyLazyBuilder =
  | Mylazy
  member this.Bind(x, f) =
      match x with
       | Lz(xa, xe) -> 
             Lz(xa, fun x -> force (f (xe x)))
  member this.Return(x) = pack x

let sth =
    Mylazy {
        let! x = pack 12
        let! y = pack (x + 1)
        return y * x
    }
let res = force sth

缺少force仅评估一次的部分)。

迟到了,但认为值得建议。

I'm not sure this helps, but you can avoid using the lazy keyword altogether if you particularly want to for some reason:

type ('a, 'b) lazyT = Lz of 'a * ('a -> 'b)

let force (Lz (a, e)) = e a
let pack x = Lz(x, (fun i -> i))

type MyLazyBuilder =
  | Mylazy
  member this.Bind(x, f) =
      match x with
       | Lz(xa, xe) -> 
             Lz(xa, fun x -> force (f (xe x)))
  member this.Return(x) = pack x

let sth =
    Mylazy {
        let! x = pack 12
        let! y = pack (x + 1)
        return y * x
    }
let res = force sth

(absent the part where force only evaluates it once).

Late, but thought it was worth suggesting.

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