Cyclic function/type dependency in F#

倾然丶 夕夏残阳落幕 提交于 2019-12-10 23:04:44

问题


I have a question about the best way to go about the following

I Have a class B, I have a combinator on B, let foo : B -> int.

I want the class B to have the combinator encapsulated as a method, so I add it with a type extension.

I then later on realize that foo is quite expensive and want to cache it's result with lazy evaluation

So I add a huge clutch to the system by passing the combinator as a function to the constructor and then initializing a field with foo = lazy(foo self) in the constructor.

i.e.

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)

this obviously feels wrong

the two options I see for fixing this are 1, make an interface and have foo inherit that interface, 2, make everything a static method and then make combinators out of those static methods(sort of the opposite of attaching them to classes...)

Neither of these are hugely appealing and I was wondering if I missed option 3

Oh, and I haven't been able to get let rec and to work quite right with this, nor would i really want to as "something" in the above statement depends on a function that depends on a function that depends on a function(3 deep).

any advice would be appreciated


回答1:


I don't think there is anything wrong with your current design. The key point is that if you define the type Foo as well as the extension to the type in a same file (and the same module), then F# will combine the two parts of the definition into a single .NET type. So, the fact that it is defined in two separate parts is just an implementation detail.

If you don't want to expose the constructor that takes the combinator, you can mark it as private. Together with a few additional changes (i.e. use implicit constructor syntax), the snippet would look like this:

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

let something (x:Foo) = 1

type Foo with
  new() = Foo(something)

If you want to keep something as a separate function, then this is a fine solution. Many numeric types in the F# PowerPack follow this pattern (see for example definition of complex numbers)




回答2:


I don't quite grok what you're after, but I think this may help:

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

A type can be recursive with its own static member, so this is a simpler way to write your code.



来源:https://stackoverflow.com/questions/5559699/cyclic-function-type-dependency-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!