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

时间:2011-04-05 23:18:39

标签: f# cyclic-reference

我对以下

的最佳方式有疑问

我有一个B级,我在B上有一个组合器, 让foo:B - >中间体

我希望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,创建一个接口并让foo继承该接口,2,使所有东西成为静态方法,然后用这些静态方法组合组合(与将它们附加到类相反的方式) ...)

这些都不是很吸引人,我想知道我是否错过了选项3

哦,我还没有能够让rec和工作做得很好,我也不会真的想在上面的语句中“某事”依赖于依赖于依赖于函数的函数一个函数(3深)。

任何建议都将不胜感激

2 个答案:

答案 0 :(得分: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)

如果您想将something作为单独的函数,那么这是一个很好的解决方案。 F#PowerPack中的许多数字类型都遵循此模式(请参阅例如definition of complex numbers

答案 1 :(得分:2)

我不太了解你所追求的是什么,但我认为这可能会有所帮助:

type foo(comb) as self =
    let x = lazy(comb self)
    static member something (x:foo) = 1 
    new() = foo(foo.something)

一个类型可以使用自己的静态成员递归,因此这是编写代码的一种更简单的方法。