Могут ли члены типа F # ссылаться друг на друга? - PullRequest
4 голосов
/ 07 апреля 2011

Мне было интересно, есть ли способ позволить членам типа ссылаться друг на друга. Я хотел бы написать следующую программу, как это:

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 не может увидеть это. Я могу понять почему, но кажется, что большинство функциональных языков имеют способ сообщить функциям, что они существуют заранее, так что возможен тот или иной синтаксис.

Вместо этого мне пришлось сделать следующее, что не намного больше кода, но кажется, что первое будет выглядеть более элегантно, чем второе, особенно если таких случаев больше.

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 ]

6 голосов
/ 07 апреля 2011

Если класс является не чем иным, как реализацией интерфейса, вы можете использовать объектное выражение.Я предпочитаю это, когда это возможно, для краткости.

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();
6 голосов
/ 07 апреля 2011

Попробуйте следующее:

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
...