f# - F# 中的循环函数/类型依赖

标签 f# cyclic-reference

我对执行以下操作的最佳方法有疑问

我有一个 B 类,我在 B 上有一个组合器, 让 foo : B -> int。

我希望类 B 将组合器封装为方法,因此我添加了类型扩展。

后来我意识到 foo 相当昂贵,并且想通过延迟评估来缓存它的结果

因此,我通过将组合器作为函数传递给构造函数,然后在构造函数中使用 foo = lazy(foo self) 初始化字段,为系统添加了一个巨大的离合器。

type foo =
    class
        val x : int Lazy

         new (comb) as self = {x=lazy(comb self);}
     end
 let something (x:foo) = 1

 type foo with
      new() = foo(something)

这显然感觉不对

我看到的解决这个问题的两个选项是1,创建一个接口(interface)并让foo继承该接口(interface),2,将所有内容都设为静态方法,然后从这些静态方法中创建组合器(与将它们附加到类相反) ...)

这两个都没有太大吸引力,我想知道我是否错过了选项 3

哦,我还无法得到 let rec 并能很好地处理这个问题,我也不想这样做,因为上面语句中的“某些东西”取决于一个函数,而这个函数又依赖于一个函数,而这个函数又依赖于一个函数。一个函数(3 深)。

如有任何建议,我们将不胜感激

最佳答案

我认为您当前的设计没有任何问题。关键点是,如果您在同一文件(和同一模块)中定义类型 Foo 以及该类型的扩展,那么 F# 会将定义的两部分合并为一个.NET 类型。因此,它被定义为两个单独的部分这一事实只是一个实现细节。

如果您不想公开采用组合器的构造函数,可以将其标记为private。加上一些额外的更改(即使用隐式构造函数语法),代码片段将如下所示:

type Foo private (comb) as self =
  let x : Lazy<int> = lazy comb self

let something (x:Foo) = 1

type Foo with
  new() = Foo(something)

如果您想将某些东西保留为单独的函数,那么这是一个很好的解决方案。 F# PowerPack 中的许多数字类型都遵循此模式(例如,参见 definition of complex numbers )

关于f# - F# 中的循环函数/类型依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5559699/

相关文章:

java - 如何在 Java 中实例化具有相互循环引用的类,而不必使用 `NULL`?

c++ - 如何使用 std::shared_ptr 检测或避免循环引用?

c++ - 试图解决我的双端队列类和树类之间的循环引用错误

f# - 同名的模块和类

F#在不匹配的情况下提取可区分联合内的值

f# - 单线程程序在 semaphore_wait_trap 中分析 15% 的运行时间

algorithm - 为什么我们需要检测链表中的循环

f# - Xamarin.Forms 是否支持 F#?

f# - 如何优雅地合并具有指定键的两个元组序列?

rust - 在 Rust 中引用一个包含结构(并调用它的方法)