C# 的 Func 和 TimeSpan 的可区分联合
Discriminated Union of Func and TimeSpan for C#
我刚接触 F# 大约 2 小时,在弄清楚如何声明可以是 Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>>
或 TimeSpan
.
的可区分联合类型时遇到了一些问题
namespace Test
open System
type FuncOrTimeSpan =
// Should this be written in a different way to be able to take fun (a, b, c) -> ...?
| Func of Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>>
| TimeSpan of TimeSpan
module ThingDoer
let (|ActiveThing|_|) input = Option.Some(1)
// Do I need to tell this function that I expect it to return FuncOrTimeSpan?
let ReturnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> FuncOrTimeSpan.TimeSpan(TimeSpan.FromSeconds(10))
| ActiveThing number -> FuncOrTimeSpan.Func(fun (a, b, c) -> Option.Some(DateTime.Now))
我因为以下原因而大喊大叫:这个函数接受了太多的参数,或者在不需要函数的上下文中使用。
我该怎么做才能将 lambda 传递给 FuncOrTimeSpan.Func
?
此外,我是否应该将 Func of Func<DateTime, DateTime, Option<DateTime>
重写为 Func of DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>
之类的东西?我不知道这意味着什么,我试过也没用。
我可能应该注意到,我计划从 C# 连接这个函数(但也许应该连接它的 C# 部分也将重写为 F#,因此仍然欢迎打破互操作的解决方案)。
您需要将 curry 结果转换为 System.Func
let ReturnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" ->
let timespan = TimeSpan.FromSeconds(10.0)
FuncOrTimeSpan.TimeSpan(timespan)
| ActiveThing number ->
let curryResult = fun (a : DateTime) (b:DateTime) (c:DateTime option) -> Some(DateTime.Now)
let funcResult = System.Func<_,_,_,_>(curryResult)
FuncOrTimeSpan.Func(funcResult)
如果不知道你的意图到底是什么,很难回答这个问题,所以对你试图解决的问题进行定性描述将有助于给出明确的答案,不过我会尽力而为。
首先,您的类型定义应该如下所示:
type FuncOrTimeSpan =
| Func of (DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
我没有发现您当前的类型定义有任何问题,但是使用 System.Func
.
编写 F# 函数非常不寻常
如果你想要元组参数而不是柯里化参数,你可以这样写:
type FuncOrTimeSpan =
| Func of (DateTime * DateTime * Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
虽然您正在学习,但我建议您坚持第一个,直到您找出差异。基本上,柯里化参数允许方便的部分应用,而元组参数允许方便地分组 parameters/returns。有关 F# 中柯里化的更多详细信息,请参阅 https://fsharpforfunandprofit.com/posts/currying/。
无论如何,继续第一个类型定义,您的函数将如下所示:
let returnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0))
| ActiveThing number -> Func(fun a b c -> Some(DateTime.Now))
我不知道您为什么要使用这个 ActiveThing
部分活动模式,因为它什么都不做。它只需要任何参数和 returns Some 1
所以你不妨用通配符替换它。
let returnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0))
| _ -> Func(fun a b c -> Some(DateTime.Now))
此函数 returns 一种代数数据类型,包含 1) 10 秒的时间跨度(如果您将字符串 "should return TimeSpan" 作为参数)或 2) 类型为 [=17 的柯里化函数=](最终 returns DateTime.Now
对于任何提供的参数)否则。
我刚接触 F# 大约 2 小时,在弄清楚如何声明可以是 Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>>
或 TimeSpan
.
namespace Test
open System
type FuncOrTimeSpan =
// Should this be written in a different way to be able to take fun (a, b, c) -> ...?
| Func of Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>>
| TimeSpan of TimeSpan
module ThingDoer
let (|ActiveThing|_|) input = Option.Some(1)
// Do I need to tell this function that I expect it to return FuncOrTimeSpan?
let ReturnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> FuncOrTimeSpan.TimeSpan(TimeSpan.FromSeconds(10))
| ActiveThing number -> FuncOrTimeSpan.Func(fun (a, b, c) -> Option.Some(DateTime.Now))
我因为以下原因而大喊大叫:这个函数接受了太多的参数,或者在不需要函数的上下文中使用。
我该怎么做才能将 lambda 传递给 FuncOrTimeSpan.Func
?
此外,我是否应该将 Func of Func<DateTime, DateTime, Option<DateTime>
重写为 Func of DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>
之类的东西?我不知道这意味着什么,我试过也没用。
我可能应该注意到,我计划从 C# 连接这个函数(但也许应该连接它的 C# 部分也将重写为 F#,因此仍然欢迎打破互操作的解决方案)。
您需要将 curry 结果转换为 System.Func
let ReturnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" ->
let timespan = TimeSpan.FromSeconds(10.0)
FuncOrTimeSpan.TimeSpan(timespan)
| ActiveThing number ->
let curryResult = fun (a : DateTime) (b:DateTime) (c:DateTime option) -> Some(DateTime.Now)
let funcResult = System.Func<_,_,_,_>(curryResult)
FuncOrTimeSpan.Func(funcResult)
如果不知道你的意图到底是什么,很难回答这个问题,所以对你试图解决的问题进行定性描述将有助于给出明确的答案,不过我会尽力而为。
首先,您的类型定义应该如下所示:
type FuncOrTimeSpan =
| Func of (DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
我没有发现您当前的类型定义有任何问题,但是使用 System.Func
.
如果你想要元组参数而不是柯里化参数,你可以这样写:
type FuncOrTimeSpan =
| Func of (DateTime * DateTime * Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
虽然您正在学习,但我建议您坚持第一个,直到您找出差异。基本上,柯里化参数允许方便的部分应用,而元组参数允许方便地分组 parameters/returns。有关 F# 中柯里化的更多详细信息,请参阅 https://fsharpforfunandprofit.com/posts/currying/。
无论如何,继续第一个类型定义,您的函数将如下所示:
let returnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0))
| ActiveThing number -> Func(fun a b c -> Some(DateTime.Now))
我不知道您为什么要使用这个 ActiveThing
部分活动模式,因为它什么都不做。它只需要任何参数和 returns Some 1
所以你不妨用通配符替换它。
let returnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0))
| _ -> Func(fun a b c -> Some(DateTime.Now))
此函数 returns 一种代数数据类型,包含 1) 10 秒的时间跨度(如果您将字符串 "should return TimeSpan" 作为参数)或 2) 类型为 [=17 的柯里化函数=](最终 returns DateTime.Now
对于任何提供的参数)否则。