Reputation: 13089
I have some types like this:
type Workshop = { Start: DateTime; End: DateTime }
type Mounting = { Start: DateTime; End: DateTime }
type FixedWorkTime = { Start: DateTime; End: DateTime }
type WorkTime =
| Workshop of Workshop
| Mounting of Mounting
type ApprovedWorkTime =
| ExistingWorkTime of WorkTime
| FixedWorkTime of FixedWorkTime
Now I want to create a function with this signature WorkTime -> ApprovedWorkTime
let FixWorkTime (workTime: WorkTime) : ApprovedWorkTime =
match workTime with
| WorkTime.Workshop workshop -> ApprovedWorkTime.ExistingWorkTime { Start = workshop.Start, End = workshop.End }
| WorkTime.Mounting mounting -> ApprovedWorkTime.FixedWorkTime { Start = mounting.Start, End = mounting.End }
The match
fails to compile with this error:
This expression was expected to have type 'WorkTime' but here has type 'FixedWorkTime'
How can I fix this?
Upvotes: 1
Views: 70
Reputation: 8551
The easy fix is to make the types match, as other answers already explained:
let FixWorkTime (workTime: WorkTime) : ApprovedWorkTime =
match workTime with
| WorkTime.Workshop _ -> ExistingWorkTime workTime
| WorkTime.Mounting mounting -> FixedWorkTime { Start = mounting.Start; End = mounting.End }
However, I'd probably change your types a bit to make them more composable:
type Interval = { Start: DateTime; End: DateTime }
type WorkTime =
| Workshop of Interval
| Mounting of Interval
type ApprovedWorkTime =
| ExistingWorkTime of WorkTime
| FixedWorkTime of Interval
let FixWorkTime (workTime: WorkTime) : ApprovedWorkTime =
match workTime with
| Workshop _ -> ExistingWorkTime workTime
| Mounting interval -> FixedWorkTime interval
Upvotes: 2
Reputation: 80734
Here:
ApprovedWorkTime.ExistingWorkTime { Start = workshop.Start, End = workshop.End }
You're trying to construct a value of ApprovedWorkTime
with the ExistingWorkTime
constructor, and you're passing it a record as a parameter.
But according to its definition:
| ExistingWorkTime of WorkTime
It does not expect a record, or expects a value of type WorkTime
.
So the shortest way to fix it would be to it workTime
as a parameter:
ApprovedWorkTime.ExistingWorkTime workTime
Although I severely doubt that this is what you meant to do.
Separately I'd like to point out that your types are needlessly complicated. Look: every single value has the same fields, and they only differ in their constructors, and you have to shovel those fields back and forth every time you convert between values.
A more efficient model would have the Start
and End
fields at the top level, and the kind of work as a third field:
type WorkTime<'kind>= { Start: DateTime; End: DateTime; Kind: 'kind }
type WorkTimeKind = Workshop | Mounting
type ApprovedWorkTimeKind = ExistingWorkTime of WorkTime | FixedWorkTime
Upvotes: 2
Reputation: 3470
Use semicolons, not commas, between the fields of the records. Whenever you see a comma, assume that means a tuple.
Second, ExistingWorkTime is of WorkTime, which is also a DU, so you have a hierarchy.
let fixWorkTime (workTime: WorkTime) : ApprovedWorkTime =
match workTime with
| Workshop workshop -> ExistingWorkTime (Workshop { Start = workshop.Start; End = workshop.End })
| Mounting mounting -> FixedWorkTime { Start = mounting.Start; End = mounting.End }
Upvotes: 3