Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#类型成员是否可以相互引用?_F#_Members - Fatal编程技术网

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

F#类型成员是否可以相互引用?,f#,members,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.Rol

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

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
但是,this.RollD66无法看到this.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
有什么建议吗?谢谢

尝试以下操作:

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#默认隐式实现接口):


如果类只是一个接口实现,那么可以使用对象表达式。如果可能的话,我更喜欢这个,因为它简洁

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 }
C#
我喜欢这样,但似乎我必须放弃名称空间,因为在使用名称空间时,不可能有浮动的,让我们在没有封闭类型的情况下使用。我想大概是这样因为我引用了C#中的代码,所以拥有它们真的很方便。不过,我意识到这超出了我在问题中提出的范围。你不必放弃名称空间。我更新了代码来演示。在F#和C#中可以让相同的API感觉非常自然。谢谢提示。这两种选择我都没有想到。:)但也不确定这两种方法是否更简洁。我想第一个是,但看起来确实更混乱。两个都不想比另一个更简洁;后一个版本的用法通常会更简洁。公平地说,我要求的是优雅而不是简洁。我打字的时候脑子有点乱。这两个词的用法不一样吗?@McMuttons:不,一点也不一样。使用前者,您不仅可以实例化一个
DieRoller
对象并调用其中任何一个方法;您首先必须转换到
IDieRoller
。这就是我所说的“显式接口实现”。啊,好的,我明白你的意思了。谢谢你的解释。这两个答案都很好,但是我必须选择一个,然后选择一个可能更接近我的用法的答案。谢谢你的帮助!
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 }
open MyNamespace.DieRoller
let dieRoller = makeDieRoller()
using MyNamespace;
var dieRoller = DieRoller.Create();