我对以下
的最佳方式有疑问我有一个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深)。
任何建议都将不胜感激
答案 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)
一个类型可以使用自己的静态成员递归,因此这是编写代码的一种更简单的方法。