在F#中将函数作为参数传递

时间:2014-08-27 22:28:14

标签: f#

在以下示例中,我收到错误"没有重载符合方法' op_Subtraction'。"

open System

type EmployeeStatus = 
    | Active
    | NotActive

type EnrollmentPeriod = 
    | JanuaryFirst
    | JulyFirst
    | PeriodNotApplicable

let DetermineTargettedEnrollmentDate targettedEnrollmentDate (relativeDate : DateTime) = 
    match targettedEnrollmentDate with
    | EnrollmentPeriod.JanuaryFirst -> new DateTime(relativeDate.Year + 1,1,1)
    | EnrollmentPeriod.JulyFirst -> new DateTime(relativeDate.Year,7,1)
    | EnrollmentPeriod.PeriodNotApplicable -> relativeDate

let ProjectDaysWorkedSinceJan1 employeeStatus targettedEnrollmentPeriod (relativeDate : DateTime) =
    let januaryFirst = DateTime(relativeDate.Year,1,1)
    let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod
    match employeeStatus with
    | Active -> int (januaryFirst - targettedEnrollmentDate).TotalDays
    | NotActive -> 0

targettedEnrollmentDate函数确定DetermineTargettedEnrollmentDate似乎并非如此。

我在哪里错了?

2 个答案:

答案 0 :(得分:4)

您只向DetermineTargettedEnrollmentDate提供第一个参数:

let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod

结果是等待第二个参数的函数,即targettedEnrollmentDate是一个以relativeDate为参数的函数。

因此,您尝试做的是从日期中减去一个函数,这是编译器抱怨的内容。

答案 1 :(得分:1)

我真的不明白你的问题。代码显然没有编译。

DetermineTargettedEnrollmentDate定义为

val DetermineTargettedEnrollmentDate :
  targettedEnrollmentDate:EnrollmentPeriod ->
    relativeDate:DateTime -> DateTime

这意味着,它需要两个参数:EnrollmentPeriodDateTime并返回另一个DateTime。稍后在ProjectDaysWorkedSinceJan1中,您只使用一个参数:

let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod

由于partial application,这会使targettedEnrollmentDate成为一个函数,需要DateTime并返回另一个DateTime。但是当你试图从中减去另一个DateTime时,你会尝试使用它,就像它是一个值一样。

      | Active -> int (januaryFirst - targettedEnrollmentDate).TotalDays
  ----------------------------------^

(...)

Possible overload: 'DateTime.op_Subtraction(d1: DateTime, d2: DateTime) : TimeSpan'. Type constraint mismatch. The type 
    DateTime -> DateTime    
is not compatible with type
    DateTime    

你可能想要的是用DetermineTargettedEnrollmentDate来代替relativeDate

let ProjectDaysWorkedSinceJan1 employeeStatus targettedEnrollmentPeriod (relativeDate :  DateTime) =
    let januaryFirst = DateTime(relativeDate.Year,1,1)
    let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod relativeDate
    match employeeStatus with
    | Active -> int (januaryFirst - targettedEnrollmentDate).TotalDays
    | NotActive -> 0

这使得它使用以下结果进行编译:

val ProjectDaysWorkedSinceJan1 :
  employeeStatus:EmployeeStatus ->
    targettedEnrollmentPeriod:EnrollmentPeriod -> relativeDate:DateTime -> int