Понимание случаев объединения

#f#

#f#

Вопрос:

У меня есть такие типы, как этот:

 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  

Теперь я хочу создать функцию с этой подписью WorkTime -gt; ApprovedWorkTime

 let FixWorkTime (workTime: WorkTime) : ApprovedWorkTime =  match workTime with  | WorkTime.Workshop workshop -gt; ApprovedWorkTime.ExistingWorkTime { Start = workshop.Start, End = workshop.End }  | WorkTime.Mounting mounting -gt; ApprovedWorkTime.FixedWorkTime { Start = mounting.Start, End = mounting.End }  

match Не удается выполнить компиляцию с этой ошибкой:

 This expression was expected to have type 'WorkTime' but here has type 'FixedWorkTime'  

Как я могу это исправить?

Ответ №1:

Используйте точки с запятой, а не запятые, между полями записей. Всякий раз, когда вы видите запятую, предполагайте, что это означает кортеж.

Во-вторых, существующее рабочее время относится к рабочему времени, которое также является DU, поэтому у вас есть иерархия.

 let fixWorkTime (workTime: WorkTime) : ApprovedWorkTime =  match workTime with  | Workshop workshop -gt; ExistingWorkTime (Workshop { Start = workshop.Start; End = workshop.End })  | Mounting mounting -gt; FixedWorkTime { Start = mounting.Start; End = mounting.End }  

Ответ №2:

Простое решение заключается в том, чтобы привести типы в соответствие, как уже объяснялось в других ответах:

 let FixWorkTime (workTime: WorkTime) : ApprovedWorkTime =  match workTime with  | WorkTime.Workshop _ -gt; ExistingWorkTime workTime  | WorkTime.Mounting mounting -gt; FixedWorkTime { Start = mounting.Start; End = mounting.End }  

Тем не менее, я бы, вероятно, немного изменил ваши типы, чтобы сделать их более составными:

 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 _ -gt; ExistingWorkTime workTime  | Mounting interval -gt; FixedWorkTime interval  

Ответ №3:

Здесь:

 ApprovedWorkTime.ExistingWorkTime { Start = workshop.Start, End = workshop.End }  

Вы пытаетесь создать значение ApprovedWorkTime с ExistingWorkTime помощью конструктора и передаете ему запись в качестве параметра.

Но в соответствии с его определением:

 | ExistingWorkTime of WorkTime  

Он не ожидает записи или ожидает значения типа WorkTime .

Таким образом, самый короткий способ исправить это-использовать его workTime в качестве параметра:

 ApprovedWorkTime.ExistingWorkTime workTime  

Хотя я сильно сомневаюсь, что это то, что вы хотели сделать.


Отдельно я хотел бы отметить, что ваши типы излишне сложны. Посмотрите: каждое отдельное значение имеет одни и те же поля, и они отличаются только своими конструкторами, и вам приходится перелопачивать эти поля туда и обратно каждый раз, когда вы конвертируете значения.

Более эффективная модель будет иметь поля Start и End на верхнем уровне и вид работы в качестве третьего поля:

 type WorkTimelt;'kindgt;= { Start: DateTime; End: DateTime; Kind: 'kind }  type WorkTimeKind = Workshop | Mounting  type ApprovedWorkTimeKind = ExistingWorkTime of WorkTime | FixedWorkTime