Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

regular expressions f#

How do I do regular expressions using a functional approach? Currently I want the user entering an input and even if they enter it in capital letters it will still give a response? I am unsure of how to implement this.

open System
open System.Drawing 
open System.Windows.Forms

let (|Hello|Bye|None|) input =
match input with
    | "hello" | "hi" | "morning" 
            -> Hello
    | "Goodbye" | "bye" | "go"
            -> Bye
    | _     
            -> None

   let rand = new Random()

   let hello_response () =
   let n = rand.Next(10) 
   match n with
    | 0 -> "How do you do."
    | 1 -> "Is nice talking to you."
    | 2 -> "Tell me something new."
    | 3 -> "Nice to meet you."
    | 4 -> "My pleasure."
    | 5 -> "Hi."
    | 6 -> "Hello."
    | 7 -> "Good day."
    | 8 -> "Salutation!"
    | 9 -> "Welcome!"


    let good_bye_response () =
    let n = rand.Next(10) 
    match n with
    | 0 -> "Talk to you soon."
    | 1 -> "It was nice talking to you."
    | 2 -> "Good bye."
    | 3 -> "Stay a bit longer."
    | 4 -> "Adios amigo."
    | 5 -> "Bye."
    | 6 -> "Adios."
    | 7 -> "See you."
    | 8 -> "Please don't go"
    | 9 -> "Why are you leaving me alone?"

    let none_response (str:string) =
    let n = rand.Next(10) 
    match n with
    | 0 -> "Maybe."
    | 1 -> "Perhaps " + str 
    | 2 -> "Yes."
    | 3 -> "Ah!"
    | 4 -> "Whatever." 
    | 5 -> "Sorry, the chat closed unexpectedly. What was your last 
    question?"
    | 6 -> "Where were we? I losed track of the conversation."
    | 7 -> "Very interesting"
    | 8 -> "Wow!"
    | 9 -> "Mmmmmm!"

    let rec response (token: string) (str: string) =
    match token with
    | Hello
        -> hello_response ()
    | Bye
        -> good_bye_response ()
    | "" 
        -> none_response str
    | None when (str.IndexOf(" ") > 0) 
        -> response (str.Substring(0,str.IndexOf(" "))) 
    (str.Substring(str.IndexOf(" ")+1))
    | None when (str.IndexOf(" ") < 0) 
        -> response str ""
    | None 
        -> str

    let marketbot_resp (str: string) =
    if (str.IndexOf(" ") > 0) then
    response (str.Substring(0,str.IndexOf(" "))) 
    (str.Substring(str.IndexOf(" ")+1)) + "\n"
    else
    response str "" + "\n"
like image 836
minal.m Avatar asked May 08 '17 20:05

minal.m


1 Answers

You can use regular expressions from F# exactly the same way you would from C# or VB.NET (or any other .NET language). MSDN provides quite extensive documentation on the subject. Check it out.

The root class is System.Text.RegularExpressions.Regex. The simplest way to match is through the IsMatch static method:

let (|Hello|Bye|None|) input =
    if Regex.IsMatch( input, "(?i)hello|hi|morning" ) then Hello
    elif Regex.IsMatch( input, "(?i)goodbye|bye|go" ) then Bye
    else None

You can also "cache" the regular expression by creating an instance of Regex and reusing it. This will save you a tiny bit on performance:

let (|Hello|Bye|None|) =
    let hello = Regex "(?i)hello|hi|morning"
    let bye = Regex "(?i)goodbye|bye|go"
    fun input ->
        if hello.IsMatch input then Hello
        elif bye.IsMatch input then Bye
        else None

However, for this particular task I think regular expressions are overkill. I would just convert the string to lower case before matching:

let (|Hello|Bye|None|) (input: string) =
    match input.ToLower() with
    | "hello" | "hi" | "morning" 
            -> Hello
    | "goodbye" | "bye" | "go"
            -> Bye
    | _     
            -> None
like image 89
Fyodor Soikin Avatar answered Sep 24 '22 05:09

Fyodor Soikin