开发者

Cyclic function/type dependency in F#

开发者 https://www.devze.com 2023-02-22 02:40 出处:网络
I have a question about the best way to go about the following I Have a class B, I have a combinator on B,

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

  开发者_C百科       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


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)


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消