F#:需要帮助将C#转换为F#

rys*_*ama 4 c# f#

我正在尝试为子弹地狱游戏编写一个小小的脚本引擎,我想在F#中进行.我写了一些C#代码来概念化它,但是我把它移植到F#时遇到了麻烦.C#代码发布在下面,我想帮助将它移植到F#.我觉得匹配的F#代码会明显变小.我愿意接受任何创造性的解决方案:)

interface IRunner
{
    Result Run(int data);
}

struct Result
{
    public Result(int data, IRunner next)
    {
        Data = data;
        Next = next;
    }
    public int Data;
    public IRunner Next;
}

class AddOne : IRunner
{
    public Result Run(int data)
    {
        return new Result(data + 1, null);
    }
}

class Idle : IRunner
{
    public Result Run(int data)
    {
        return new Result(data, null);
    }
}

class Pair : IRunner
{
    IRunner _one;
    IRunner _two;

    public Pair(IRunner one, IRunner two)
    {
        _one = one;
        _two = two;
    }

    public Result Run(int data)
    {
        var res = _one.Run(data);
        if (res.Next != null)
            return new Result(res.Data, new Pair(res.Next, _two));
        return new Result(res.Data, _two);
    }
}

class Repeat : IRunner
{
    int _counter;
    IRunner _toRun;

    public Repeat(IRunner toRun, int counter)
    {
        _toRun = toRun;
        _counter = counter;
    }

    public Result Run(int data)
    {
        var res = _toRun.Run(data);
        if (_counter > 1)
        {
            if (res.Next != null)
                return new Result(res.Data,
                            new Pair(res.Next,
                                new Repeat(_toRun, _counter - 1)));
            return new Result(res.Data, new Repeat(_toRun, _counter - 1));
        }
        return res;
    }
}

class Sequence : IRunner
{
    IEnumerator<IRunner> _runner;

    public Sequence(IEnumerator<IRunner> runner)
    {
        _runner = runner;
    }
    public Result Run(int data)
    {
        var res = _runner.Current.Run(data);
        bool next = _runner.MoveNext();
        if (res.Next != null)
        {
            return new Result(res.Data,
                        new Pair(res.Next, new Sequence(_runner)));
        }

        return new Result(res.Data, new Sequence(_runner));
    }
}
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 9

这几乎是对同一解决方案策略的直接翻译.

也就是说,我认为可能有一个更好/更简单的表示选择,我仍然在考虑它.

type Runner = int -> Result
and Result = Result of int * option<Runner>

let AddOne = fun x -> Result(x+1, None)

let Idle = fun x -> Result(x, None)

let rec Pair(r1,r2) = fun x ->
    match r1 x with
    | Result(data,None) -> Result(data, Some(r2))
    | Result(data,Some(next)) -> Result(data,Some(Pair(next,r2)))

let rec Repeat r n = fun x ->
    if n = 0 then r x else
    match r x with
    | Result(data,None) -> Result(data, Some(Repeat r (n-1)))
    | Result(data,Some(next)) -> Result(data, Some(Pair(next, Repeat r (n-1))))
Run Code Online (Sandbox Code Playgroud)

编辑

这是另一种更精致的方式......我仍然试图看看是否有一种很好的方式在"列表"中工作,因为结果似乎与cons细胞同构......

type Runner = Runner of (int -> int * option<Runner>)

let AddOne = Runner(fun x -> x+1, None)

let Idle = Runner(fun x -> x, None)

let rec Pair(Runner(r1),R2) = Runner(fun x ->
    match r1 x with
    | data,None -> data, Some(R2)
    | data,Some(next) -> data, Some(Pair(next,R2)))

let rec Repeat (Runner(r) as R) n = Runner(fun x ->
    if n = 0 then r x else
    match r x with
    | data,None -> data, Some(Repeat R (n-1))
    | data,Some(next) -> data, Some(Pair(next, Repeat R (n-1))))
Run Code Online (Sandbox Code Playgroud)

编辑

还有一个版本,它使用了列表,但现在我对这里有什么奇怪的感觉......

type Runner = Runner of (int -> int * list<Runner>)

let AddOne = Runner(fun x -> x+1, [])

let Idle = Runner(fun x -> x, [])

let rec Pair(Runner(r1),R2) = Runner(fun x ->
    match r1 x with
    | data,xs -> data, xs @ [R2]) // inefficient

let rec Repeat (Runner(r) as R) n = Runner(fun x ->
    if n = 0 then r x else
    match r x with
    | data,xs -> data, xs @ List.init (n-1) (fun _ -> R)) // inefficient
Run Code Online (Sandbox Code Playgroud)

它几乎就像一个'动作队列',一个int->int功能列表.但是每个人都可以产生一些"后缀动作",这些动作在他之后立即运行(但在剩余的工作在未来的队列之前),并且尝试用纯粹的功能数据结构维护排序可能是低效的(没有正确的树/手头的队列库).知道如何使用/消费这将是有趣的,因为可能会有一个小的变化可能允许完全不同的策略.


Hig*_*ark 5

忘记C#,回到设计文档(或其他)并重新实现.我的意思是,从字面上看,忘了C#.你在F#中可以做的最糟糕的事情就是编写C#.当然,这是一个通用规则的实例:你在语言X中可以做的最糟糕的事情是用Y语言编写一个程序.根据需要绑定X和Y.