我正在尝试将使用接口和Linq的c#方法转换为f#:
public static IEnumerable<ModelEngines> CurrentEngineBuilds(IEnumerable<CurrentModels> thisYearModels, DateTime startRunDate, DateTime endRunDate)
{
var engineOptions =
currentModelYear.SelectMany(c => c.Engines)
.Where(e => e.EngineProdStartDate >= startRunDate & e.EngineProdStopDate <= endRunDate);
return engineOptions;
}
在上面的方法中,我正在返回一个engineOptions的集合 - 类型是IEnumerable。我正在过滤集合,以便集合中只有具有当前模型年份的特定生产范围的engineOptions。
我在下面有这个粗略的,不起作用的翻译:
let CurrentEngineBuilds : <IEnumerable<ModelEngines>> (thisYearModels : IEnumerable<CurrentModels>) (startRunDate : DateTime) (endRunDate : DateTime) =
query {
for engineOptions in currentModelYear.engineOptions do
where (engineOptions.EngineProdStartDate >= startRunDate and engineOptions.EngineProdEndDate >= endRunDate )
select (engineOptions)
}
engineOptions
这项任务比我预期的要复杂得多。我已经通过一些f#教程来了解基础知识,但它似乎与接口和/或linq有关,这很难。
我遇到的一些问题:
有关如何进行c#到f#转换的任何提示?
答案 0 :(得分:4)
IEnumerable<'T>
在F#中被命名为seq<'T>
。在这种情况下,我没有看到任何使用LINQ query
表达式的理由;更惯用的F#翻译将使用the Seq
module:
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
thisYearModels
// v--- SelectMany
|> Seq.collect (fun c -> c.Engines)
// v--- Where
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)
如果thisYearModels
的类型未自动推断,您可以在函数签名中对其进行注释:
let CurrentEngineBuilds (thisYearModels:seq<CurrentModels>) startRunDate endRunDate = ...
或身体:
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
(thisYearModels:seq<CurrentModels>)
|> Seq.collect (fun c -> c.Engines)
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)
// or
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
thisYearModels
|> Seq.collect (fun (c:CurrentModels) -> c.Engines)
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)
答案 1 :(得分:3)
您实际上可以在F#中使用LINQ而不会出现任何问题。这是您原始示例的几乎直接端口(我假设currentModelYear
是一种类型,您的意思是thisYearModels
)
open System.Linq
let currentEngineBuilds(thisYearModels:seq<CurrentModels>, startRunDate, endRunDate) =
let engineOptions =
thisYearModels
.SelectMany(fun e -> e.Engines)
.Where(fun e -> e.StartDate >= startRunDate && e.StopDate <= endRunDate)
engineOptions // return keyword not required
出于本文的目的,您可以将seq<T>
视为IEnumerable<T>
的简写。
话虽如此,我认为您会发现Seq
模块更适合F#,因为它旨在利用F#语言功能,例如Tuples,并且可以提供帮助类型推断过程。
答案 2 :(得分:2)
|>
或&#34;管道&#34; operator是F#将函数应用于值的惯用方法。
v |> f
与之前指出的f v
相同。
query
计算表达式中使用了monadic链接,并且也是惯用语。
希望有助于将这两个(相当复杂的)概念与您的理解区分开来! :)