F#类型成员可以互相引用吗?

时间:2011-04-07 18:49:20

标签: f# members

我想知道是否有办法让类型成员互相引用。我想写下面这样的程序:

type IDieRoller =
    abstract RollDn : int -> int
    abstract RollD6 : int
    abstract RollD66 : int

type DieRoller() =
    let randomizer = new Random()

    interface IDieRoller with
        member this.RollDn max = randomizer.Next(max)
        member this.RollD6 = randomizer.Next(6)
        member this.RollD66 = (RollD6 * 10) + RollD6

但是,这个.RollD66无法看到这个.RollD6。我可以理解为什么,但似乎大多数函数式语言都有一种让函数知道它们提前存在的方法,以便这种或类似的语法成为可能。

相反,我必须做以下事情,这不是更多的代码,但似乎前者看起来比后者更优雅,特别是如果有更多这样的情况。

type DieRoller() =
    let randomizer = new Random()

    let rollD6 = randomizer.Next(6)

    interface IDieRoller with
        member this.RollDn max = randomizer.Next(max)
        member this.RollD6 = rollD6
        member this.RollD66 = (rollD6 * 10) + rollD6

任何提示?谢谢!

2 个答案:

答案 0 :(得分:6)

尝试以下方法:

open System

type IDieRoller =
    abstract RollDn : int -> int
    abstract RollD6 : int
    abstract RollD66 : int

type DieRoller() =
    let randomizer = Random()

    interface IDieRoller with
        member this.RollDn max = randomizer.Next max
        member this.RollD6 = randomizer.Next 6
        member this.RollD66 =
            (this :> IDieRoller).RollD6 * 10 + (this :> IDieRoller).RollD6

但是,您可能会发现以下更容易使用(因为F#显式实现了接口,不像C#默认隐式实现它们):

open System

type IDieRoller =
    abstract RollDn : int -> int
    abstract RollD6 : int
    abstract RollD66 : int

type DieRoller() =
    let randomizer = Random()

    member this.RollDn max = randomizer.Next max
    member this.RollD6 = randomizer.Next 6
    member this.RollD66 = this.RollD6 * 10 + this.RollD6

    interface IDieRoller with
        member this.RollDn max = this.RollDn max
        member this.RollD6 = this.RollD6
        member this.RollD66 = this.RollD66

答案 1 :(得分:6)

如果该类只是一个接口实现,则可以使用对象表达式。在可能的情况下,我更喜欢这个,因为它简洁。

namespace MyNamespace

type IDieRoller =
    abstract RollDn : int -> int
    abstract RollD6 : int
    abstract RollD66 : int

module DieRoller =

    open System

    [<CompiledName("Create")>]
    let makeDieRoller() =
        let randomizer = new Random()
        { new IDieRoller with
            member this.RollDn max = randomizer.Next max
            member this.RollD6 = randomizer.Next 6
            member this.RollD66 = this.RollD6 * 10 + this.RollD6 }

F#

open MyNamespace.DieRoller
let dieRoller = makeDieRoller()

C#

using MyNamespace;
var dieRoller = DieRoller.Create();