Joe
Joe

Reputation: 856

Passing function as argument in F#

In the following example, I'm receiving the error "No overloads match for method '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

It doesn't appear to like that targettedEnrollmentDate is being determined by the DetermineTargettedEnrollmentDate function.

Where am I going wrong here?

Upvotes: 2

Views: 889

Answers (2)

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

I don't really understand your question. The code clearly doesn't compile.

DetermineTargettedEnrollmentDate is defined as

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

Which means, it takes two parameters: an EnrollmentPeriod and a DateTime and returns another DateTime. Later in ProjectDaysWorkedSinceJan1 you use it with just one argument:

let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod

Because of partial application, this makes targettedEnrollmentDate a function, which takes DateTime and return another DateTime. But later you try to use it as if it was a value, when you try to substract another DateTime from it.

      | 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    

What you probably want is to call DetermineTargettedEnrollmentDate with relativeDate instead:

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

Which makes it compile with following result:

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

Upvotes: 1

John Reynolds
John Reynolds

Reputation: 5057

You only supply DetermineTargettedEnrollmentDate with the first argument:

let targettedEnrollmentDate = DetermineTargettedEnrollmentDate targettedEnrollmentPeriod

The result of that is a function waiting for the second argument, i.e. targettedEnrollmentDate is a function that takes relativeDate as an argument.

So, what you try to do, is subtract a function from a date and that's what the compiler complains about.

Upvotes: 4

Related Questions