Mismatch in record pattern and type on database record in F#

試著忘記壹切 提交于 2020-07-09 12:04:28

问题


How do I fix the following errors?

This expression was expected to have type 'string * Nullable * Nullable' but here has type 'VisitType' (Error occurs on "|AppointmentOnly(q.lastname, q.posting_time)).

and

Field 'appointmentTime' is not static (Error occurs on FsVisit.appointmentTime = q.appointment_time;).

(These errors occur in my attempt to download records from a PostgreSQL database via WCF into F# client).

type VisitType = 
| AppointmentOnly of name: string * postedTime: DateTime
| WalkIn of name: string * serviceTime: DateTime
| Kept of name: string * postedTime: DateTime * serviceTime: DateTime
| Open


type FsVisit =
     { appointmentTime: Nullable<DateTime>
       visitType: VisitType }
with
    member this.Name =
       match this.visitType with
       | AppointmentOnly(name=name) | WalkIn(name=name) | Kept(name=name) -> Some name
       | Open -> None

let TestGetScheduleAsync (tableDate : DateTime) =
    async {
        let! data = context.GetOfficeScheduleAsync(tableDate) |> Async.AwaitTask
        return data |> Seq.map ( fun q -> 
            FsVisit.appointmentTime = q.appointment_time;
                      match (q.lastname, q.posting_time, q.service_time) with
                      | AppointmentOnly(q.lastname, q.posting_time) -> AppointmentOnly({name = q.lastname; postedTime = q.posting_time})
                      | WalkIn(q.lastname, q.service_time) -> WalkIn({name =q.lastname; serviceTime = q.service_time})
                      | Kept(q.lastname, q.posting_time, q.service_time) -> Kept({name=q.lastname; postedTime = q.posting_time, serviceTime = q.service_time})
                      | Open -> None

        )}
         |> Async.StartAsTask

Thank you for any help.


回答1:


Tuple of lastname, posting_time, and service_time is not a value of VisitType type. So you cannot match it with VisitType discriminated union cases. I assume that posting_time and service_time are Nullable<DateTime> values (same as appointment_time) So you should match tuple with tuple and create VisitType case depending on posting_time and service_time value (Some or None). I also would remove name from matching

match (Option.ofNullable q.posting_time, Option.ofNullable q.service_time) with
| (Some postedTime, None) -> AppointmentOnly(q.lastname, postedTime)
| (None, Some serviceTime) -> WalkIn(q.lastname, serviceTime)
| (Some postedTime, Some serviceTime) -> Kept(q.lastname, postedTime, serviceTime)
| _ -> Open

You can adjust this code if you want VisitType option by returning None for Open case and Some for other cases.


Note that your code can be compilable as well if you'll add active patterns which will create so-called named partitions for your input data (tuple):

let (|AppointmentOnly|WalkIn|Kept|Open|)
    (name: string, postedTime: Nullable<DateTime>, serviceTime: Nullable<DateTime>) =
        match (Option.ofNullable postedTime, Option.ofNullable serviceTime) with
        | (Some postedTime, None) -> AppointmentOnly(name, postedTime)
        | (None, Some serviceTime) -> WalkIn(name, serviceTime)
        | (Some postedTime, Some serviceTime) -> Kept(name, postedTime, serviceTime)
        | (None, None) -> Open

Keep in mind that AppointementOnly, WalkIn, Kept, Open returned here is not a discriminated union cases - it's an active pattern records. Now you can use this active pattern to divide your input data into partitions and create corresponding VisitType cases:

match (q.lastname, q.posting_time, q.service_time) with
| AppointmentOnly(name, postedTime) -> AppointmentOnly(name, postedTime)
| WalkIn(name, serviceTime) -> WalkIn(name, serviceTime)
| Kept(name, postedTime, serviceTime) -> Kept(name, postedTime, serviceTime)
| Open -> Open

Again, here we are matching on the active pattern and then creating a discriminated union:

| AppointmentOnly(name, postedTime) -> AppointmentOnly(name, postedTime)
              ^                                    ^
     ACTIVE PATTERN IDENTIFIER                  UNION CASE           


来源:https://stackoverflow.com/questions/62667229/mismatch-in-record-pattern-and-type-on-database-record-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!