【问题标题】:Translating F# function partial application to C#将 F# 函数部分应用程序转换为 C#
【发布时间】:2015-07-17 02:37:30
【问题描述】:

我正在翻译这个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 -&gt; 'b -&gt; 'c) 的函数作为第一个参数,但是当绑定到 mapper 与部分应用程序绑定时,我有问题理解使用的 lambda 函数。

我通常将these helpers 用于部分应用程序,但我无法将此 F# 代码转换为 C#。

【问题讨论】:

    标签: c# f# functional-programming


    【解决方案1】:

    您的 Lift2 需要一个柯里化函数,但传递给 SelectMany 的映射器没有柯里化。所以让我们咖喱吧:

    Func<TSuccess, Func<TValue, TResult>> curriedMapper = suc => val => mapperFunc(suc, val);
    Func<
        Result<TSuccess, TMessage>, 
        Result<TValue, TMessage>, 
        Result<TResult, TMessage>
    > liftedMapper = (a, b) => Lift2(curriedMapper, a, b);
    var v = Bind(func, result);
    return liftedMapper(result, v);
    

    【讨论】:

    • 正是我想要做的......所以第一个是柯里化函数,第二个是部分应用程序,对吧?
    • 是的。 C# 版本在技术上不必部分应用 Lift2 来获取 LiftMapper;它可以像@scrwtp 的答案一样返回 Lift2(curriedMapper, result, Bind(func, result)) ;这也将避免其粗糙的类型声明。我只是逐行翻译。
    • 感谢这帮助我了解我哪里出错了!
    【解决方案2】:

    一般来说,lift2 接受两个简单类型参数 'a'b 的函数,并生成一个适用于包装类型 M&lt;'a&gt;M&lt;'b&gt; 的函数。否则,您可以将其视为采用三个参数:一个简单类型的函数和两个包装值,解包这些值,将函数应用于它们并包装结果。

    假设您的函数从 F# 正确移植,SelectMany 的主体将如下所示:

    return Lift2(mapper, this, Bind(func, this));
    

    奇怪的Invokes 在 F# 版本中有,因为Funcs 不像在 C# 中那样适用,你必须显式调用Invoke。此外,由于它是非咖喱的,mapper.Invoke 不能直接传递给 lift2 - 这就是它被包装在咖喱函数中的原因。

    【讨论】:

    • 我提供了一个带有行号的链接,以检查 Trial.Lift2 是否从 F# 正确移植(请参阅问题)。 mapperFunc 签名与Lift2 接受的func 不兼容。这是我的主要问题...
    • 那么我的建议是不要在 C# 版本中部分应用它。 F# 中的部分应用程序很好,因为它内置在语言中。在 C# 中,它只会增加噪音。
    • @scrtp 你的意思是没有 Lift2 吗?你将如何实现它?
    • 见我回答的第一段。您不需要部分应用lift2。这只是用 FP 语言(一个接受一个函数并返回一个提升函数的函数)来考虑它的一种自然方式。你也可以让它成为一个三个参数的函数,它接受一个函数,一次性提升它并应用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多