将F#函数部分应用程序转换为C#

时间:2015-07-16 16:40:43

标签: c# f# functional-programming

我正在翻译这个F# source用于铁路导向编程to C#

我在翻译此SelectMany重载时遇到问题:


  static member inline SelectMany (this:Result<'TSuccess, 'TMessage>, func: Func<_,_>, mapper: Func<_,_,_>) =
    let mapper = lift2 (fun a b -> mapper.Invoke(a,b))
    let v = bind func.Invoke this
    mapper this v

我已使用上面的函数签名映射:


  public static Result<TResult, TMessage> SelectMany<TSuccess, TMessage, TValue, TResult>(
    this Result<TSuccess, TMessage> result,
    Func<TSuccess, Result<TValue, TMessage>> func,
    Func<TSuccess, TValue, TResult> mapperFunc)

F#lift2函数(我认为我已正确translated)接受带有签名('a -> 'b -> 'c)的函数作为第一个参数,但绑定到mapper时绑定部分应用我有问题理解使用过的lambda函数。

我通常使用these helpers进行部分应用,但我无法将此F#代码翻译为C#。

2 个答案:

答案 0 :(得分:3)

你的Lift2期待一个curried函数,但传递给SelectMany的映射器不是curry。让我们来讨论它:

for ( i = 0; i < n; i++ )   // Code for LIS
{
    for ( j = 0; j < i; j++ )
    {
        if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
            lis[i] = lis[j] + 1;
    }
}

for ( i = 0; i < n; i++ )   // Code for LDS
{
    for ( j = 0; j < i; j++ )
    {
        if (arr[i]  < arr[j] && lds[i] < lds[j] + 1)
            lds[i] = lds[j] + 1;
    }
}

答案 1 :(得分:1)

通常,lift2采用简单类型'a'b的两个参数的函数,并生成一个适用于包装类型M<'a>和{{1}的函数}。否则,您可以将其视为三个参数:一个函数优于简单类型和两个包装值,展开这些值,将函数应用于它们并包装结果。

假设您的功能已从F#正确移植,M<'b>的正文将如下所示:

SelectMany

奇怪的return Lift2(mapper, this, Bind(func, this)); 存在于F#版本中,因为Invokes不适用于C#,您必须明确调用Funcs。此外,由于它没有结果,Invoke无法直接传递到mapper.Invoke - 这就是为什么它被包裹在一个curried函数中。