我距离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#,所以仍然欢迎破解互操作的解决方案。)
答案 0 :(得分:3)
在不知道你的意图究竟是什么的情况下很难回答这个问题,所以对你试图解决的问题的定性描述将有助于给出一个明确的答案,我会尽我所能虽然。
首先,您的类型定义应如下所示:
type FuncOrTimeSpan =
| Func of (DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
我没有看到您当前的类型定义有任何问题,但使用System.Func
编写F#函数非常不寻常。
如果你想要tupled而不是curried参数,你可以这样写:
type FuncOrTimeSpan =
| Func of (DateTime * DateTime * Option<DateTime> -> Option<DateTime>)
| TimeSpan of TimeSpan
虽然你在学习,但我建议你坚持到第一个,直到你找出差异为止。基本上,curried参数允许方便的部分应用,而tupled参数允许方便地对参数/返回进行分组。有关F#中的currying的详细信息,请参阅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
部分活动模式,因为它没有做任何事情。它只需要任何参数并返回Some 1
,所以你也可以用通配符替换它。
let returnEitherFuncOrTimeSpan input =
match input with
| "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0))
| _ -> Func(fun a b c -> Some(DateTime.Now))
此函数返回一个代数数据类型,如果你给它字符串&#34;它应该返回TimeSpan&#34;它包含1)10秒的时间跨度。作为参数或2)类型DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>
的curried函数(最终为任何提供的参数返回DateTime.Now
)否则。
答案 1 :(得分:2)
您需要将咖喱结果转换为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)