[英]Translating F# function partial application 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
函数(我认为我已经正确翻译了 )接受带有签名('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.