Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Type casting an array of strings

I have 2 arrays. Array 1 is a string array that contains the names of types.

So the contents of Array 1 looks like this:

["nvarchar";"nvarchar";"date";"nvarchar"] //these are all strings

Array 2 is another array of strings and the contents look like this:

["Jackson";"Sentzke";"1991-04-19T00:00:00";"Jackson Sentske"]

My problem is that all the values in Array 2 are strings, and I want them to be of the types in Array 1. Is there a way that I can type cast the strings in Array 2 using the strings in Array 1?

like image 980
Mark Avatar asked Oct 12 '16 08:10

Mark


1 Answers

As @s952163 points out, it looks like you're attempting to read data from a database, in which case there are better options available than trying to do it yourself. Still, just to sketch out a possible solution if taking the OP at face value, here's one way to go about it.

Since the types listed aren't .NET types, perhaps it's better to define a custom type to hold such values:

open System

type DbType = NVarChar of string | DT of DateTime

You can add more cases to DbType if you'd like.

Using active patterns, you can write a function to convert a single candidate:

// string * string -> string option
let (|NVarChar|_|) = function
    | "nvarchar", (x : string) -> Some x
    | _ -> None

// string * string -> DateTime option
let (|DT|_|) (typeHint, value) =
    match (typeHint, DateTime.TryParse value) with
    | "date", (true, dt) -> Some dt
    | _ -> None

// string * string -> DbType option    
let convertPair = function
    | NVarChar x -> Some (NVarChar x)
    | DT x -> Some (DT x)
    | _ -> None

The use of active patterns isn't strictly necessary, but I thought it enabled me to decompose the problem in a good way.

Now you can declare a list of types and one of values, zip them together to get a list of interpreted values:

> let types = ["nvarchar"; "nvarchar"; "date"; "nvarchar"];;    
val types : string list = ["nvarchar"; "nvarchar"; "date"; "nvarchar"]

> let values = ["Jackson"; "Sentzke"; "1991-04-19T00:00:00"; "Jackson Sentske"];;    
val values : string list =
  ["Jackson"; "Sentzke"; "1991-04-19T00:00:00"; "Jackson Sentske"]

> let converted = List.zip types values |> List.choose convertPair;;    
val converted : DbType list =
  [NVarChar "Jackson"; NVarChar "Sentzke"; DT 19.04.1991 00:00:00;
   NVarChar "Jackson Sentske"]

Note that both types and values have the type string list. In the OP, they were (string * string * string * string) list, which I assume was a mistake.

like image 101
Mark Seemann Avatar answered Oct 06 '22 16:10

Mark Seemann