繁体   English   中英

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

[英]Translating F# function partial application to C#

我正在将此面向铁路编程的F#源代码转换为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函数(我认为我已经正确翻译了 )接受带有签名('a -> 'b -> 'c)的函数作为第一个参数,但是当绑定到具有部分应用程序的mapper let-binding时,我就很难理解使用的lambda函数。

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

您的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);

通常, lift2接受具有简单类型'a'b的两个参数的函数,并产生对包装类型M<'a>M<'b>起作用的函数。 否则,您可以将其视为三个参数:一个简单类型的函数和两个包装的值,将这些值解包,将函数应用于它们并包装结果。

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

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

F#版本中存在奇数Invokes ,因为Funcs不适用于C#,因此您必须显式调用Invoke 此外,由于它是uncurried,一个mapper.Invoke无法通过直入lift2 -这就是为什么它包裹在一个咖喱功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM