Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enums in F# for strings

Tags:

enums

f#

I'm working on a legacy database with no systems to which I can modify. Because of type providers I decided to use F#. It's not so simple now that I'm into it. How do I structure a field in my DB that has only the following strings? It's sort of like an ENUM. I've tried the following but haven't quite gotten it.

Attempt 1

type SuspendedDriver = "SI"
type ActiveDriver = "IMPRESO"
type Applicant = "NO"
type TemporaryDriver = "TEMP"
type Uncertain = "NULL"

type DriverStatus =
    | SuspendedDriver
    | ActiveDriver
    | Applicant
    | TemporaryDriver
    | Uncertain

type Driver = {
    status : DriverStatus
    }

Error

Error FS0618: Invalid literal in type (FS0618) (ScriptTest)

Attempt 2

type DriverStatus =
    | SuspendedDriver = "SI"
    | ActiveDriver = "IMPRESO"
    | Applicant = "NO"
    | TemporaryDriver = "TEMP"
    | Uncertain = "NULL"

Error

Error FS0951: Literal enumerations must have type int, uint, int16,
uint16, int64, uint64, byte, sbyte or char (FS0951) (ScriptTest)
like image 572
ovatsug25 Avatar asked Aug 22 '16 13:08

ovatsug25


1 Answers

As mentioned in the comment, you cannot define an enum that has values erased to strings. Enums can only be integers (of various types).

Using enums in an ugly way

You could use the actual names of the enum fields and then parse them using Enum.Parse, but that's probably not good idea, because the enum cases would be fairly obscure codes. But just for the record, the following works:

type DriverStatus =
   | SI = 0

System.Enum.Parse(typeof<DriverStatus>, "SI") :?> DriverStatus

Cleaner parsing into discriminated union

In practice, I would do what Sam recommends and write a function to parse the string from the database. This has the advantage that you'll need to figure out what to do with errors in the database (the value can always be something wrong):

type DriverStatus =
   | SuspendedDriver
   | ActiveDriver

let parseDriverStatus = function
   | "SI" -> SuspendedDriver
   | "IMPRESO" -> ActiveDriver 
   | code -> failwith (sprintf "Wrong driver code! %s" code)

Using the cool Enum SQL provider

Finally, if you happen to be using MS SQL database, then the SQL Command Provider project has a neat feature that lets you automatically import enum-like types from SQL database itself, which might actually be exactly what you need in this case.

like image 155
Tomas Petricek Avatar answered Oct 28 '22 14:10

Tomas Petricek