Types of pattern matching from strings in F #

I am working on a function that matches some of my custom types in f # and converts them to strings. Some of the code looks like this:

let gsToString (gs : general_structure) : string = 
    match gs with
    | Date(Scattered(Eom(Ascending))) -> "Date(Scattered(Eom(Ascending)))"
    | Date(Scattered(Eom(SameDate(dt)))) -> "Date(Scattered(Eom(SameDate(" + dt.ToString() + "))))"
    | Number(AllNegative(Int1(Neither))) -> "Number(AllNegative(Int1(Neither)))" 
    | Number(AllNegative(Int1(SameInt(si)))) -> "Number(AllNegative(Int1(SameFloat(" + si.ToString() + "))))"

      

Many other types are mapped in this function, but there should be enough to convey the problem. In addition, the types that cause problems are:

| SameDate of System.DateTime
| SameFloat of float

      

Obviously, it's a fairly straightforward task to make the first pattern matching function that converts my general_structure types to strings. However, the problem occurs in my next function (which needs to be called later in the code) where I need to convert the string representation to general_structure again. The problem areas are as follows:

let stringToGS (str : string) : general_structure = 
    match str with
    | "Date(Scattered(Eom(Ascending)))" -> Date(Scattered(Eom(Ascending)))
    | "Date(Scattered(Eom(SameDate(dt))))"-> Date(Scattered(Eom(SameDate(System.DateTime.Parse dt))))
    | "Number(AllNegative(Int1(Neither)))" -> Number(AllNegative(Int1(Neither))) 
    | "Number(AllPositive(Float1(SameFloat(sf))))" -> Number(AllPositive(Float1(SameFloat((float) sf)))) 

      

While the first and third cases in the stringToGS function work fine, I can't seem to find a way to convert the rest back to their original form. If there is a way to take a string inside a pattern matching operator (in this case it would be dt and fs) and somehow parse just that part of the pattern to return a different value (in which case I am trying to make them System.DateTimes and Floats respectively) and return to their original forms:

Date(Scattered(Eom(SameDate(dt))))
Number(AllPositive(Float1(SameFloat(sf))))

      

? I would appreciate any help.

EDIT:

I managed to solve the problem by doing the following with the if statements for the cases that were causing the problems:

if str.Contains("Scattered(Eom(SameDate")
then 
    let p1 = str.IndexOf(")")
    let p2 = str.LastIndexOf("(")
    let dt1 = str.Remove(p1)
    let dt2 = dt1.Substring(p2 + 1)
    let date = System.DateTime.Parse dt2
    Date(Scattered(Eom(SameDate(date))))

      

Then I could just do normal pattern matching on all types with no nested data.

+3


source to share


1 answer


You can also use active templates if there are a limited number of classes and you don't want to use the serialization library:

open System

let (|RegexMatch|_|) pattern input =
    let matches = System.Text.RegularExpressions.Regex.Matches(input, pattern)
    if matches.Count = 1 then Some matches.[0].Groups.[1].Value
    else None

type GeneralStructure =
| NoPayload
| DatePayload of DateTime
| StringPayload of string option

let toString = function
| NoPayload -> "NoPayload"
| DatePayload dt -> sprintf "DatePayload(%d)" <| dt.ToBinary()
| StringPayload None -> "StringPayload(None)"
| StringPayload (Some s) -> sprintf "StringPayload(Some(%s))" s

let fromString = function
| "NoPayload" -> NoPayload
| "StringPayload(None)" -> StringPayload None
| RegexMatch @"DatePayload\((.*)\)" dt -> DatePayload <| DateTime.FromBinary(Int64.Parse dt)
| RegexMatch @"StringPayload\(Some\((.*)\)\)" msg -> StringPayload <| Some msg
| o -> failwithf "Unknown %s %s" typeof<GeneralStructure>.Name o


let serialized = StringPayload <| Some "Foo" |> toString
let deserialized = fromString serialized

let serialized' = DatePayload DateTime.UtcNow |> toString
let deserialized' = fromString serialized'

// val serialized : string = "StringPayload(Some(Foo))"
// val deserialized : GeneralStructure = StringPayload (Some "Foo")
// val serialized' : string = "DatePayload(5247430828937321388)"
// val deserialized' : GeneralStructure = DatePayload 06.08.2015 18:04:10

      



Please note that the regex is not reliable, I only did it to fit these cases.

+2


source







All Articles