Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有模式匹配的F#分支逻辑_F# - Fatal编程技术网

具有模式匹配的F#分支逻辑

具有模式匹配的F#分支逻辑,f#,F#,让我在C#上有这样的代码。如何用F#以函数形式重写此brunchin逻辑?我应该使用什么模式匹配?主动模式匹配?有区别的联合 public class DataBase { public List<string> GetEmployees(string id, string email) { if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(email)) {

让我在C#上有这样的代码。如何用F#以函数形式重写此brunchin逻辑?我应该使用什么模式匹配?主动模式匹配?有区别的联合

public class DataBase
{
    public List<string> GetEmployees(string id, string email)
    {
        if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(email))
        {
            return GetByIdAndEmail(id, email);
        }
        else if (!string.IsNullOrEmpty(email))
        {
            return GetByEmail(email);
        }
        else if (!string.IsNullOrEmpty(id))
        {
            return GetById(id);
        }
        else
        {
            return new List<string>();
        }
    }

    private List<string> GetByIdAndEmail(string id, string email)
    {
        // request something in db
        return new List<string>() { "First" };
    }

    private List<string> GetByEmail(string email)
    {
        //request something in db
        return new List<string>() { "Second" };
    }

    private List<string> GetById(string id)
    {
        // request something in db
        return new List<string>() { "Third" };
    }
}

class Program
{
    static void Main(string[] args)
    {
        DataBase DB = new DataBase();
        string id = null;
        string email = null;
        DB.GetEmployees(id, email);
    }
}

我认为这很好:

let getByIdAndEmail id email = ["First"]
let getByEmail email = ["Second"]
let getById id = ["Third"]

let getEmployees id email = 
    match String.IsNullOrEmpty id, String.IsNullOrEmpty email with
    | false, false -> getByIdAndEmail id email 
    | true, false  -> getByEmail email
    | false, true  -> getById id
    | _ -> []
如果您想利用F#type系统的强大功能及其简洁的语法,我建议您进一步编写一个新的字符串类型,确保其内容不为null或空。这样每个人在使用该类型的值时都会感到安全

type ReallyString = private ReallyString of string with
    static member Create s = match String.IsNullOrEmpty s with
                             | true -> None
                             | false -> Some (ReallyString s)
    member this.Value = let (ReallyString s) = this in s

let getByIdAndEmail (id : ReallyString) (email : ReallyString) =
    // Yay, I feel safe because the id and email really have content
    // I can use id.Value and email.Value without any worry
    ["First"]
let getByEmail (email : ReallyString) =
    // Yay, I feel safe because the email really has content
    // I can use email.Value without any worry
    ["Second"]
let getById (id : ReallyString) =
    // Yay, I feel safe because the id really has content
    // I can use id.Value without any worry
    ["Third"]

let getEmployees id email =
    // I feel unsafe here, so I have to check
    // Actually I'm being forced to check because if I don't check
    // I won't have valid values to pass to the getByXXX functions above
    match ReallyString.Create id, ReallyString.Create email with
    | Some reallyId, Some reallyEmail -> getByIdAndEmail reallyId reallyEmail
    | Some reallyId, None -> getById reallyId
    | None, Some reallyEmail -> getByEmail reallyEmail
    | _ -> []

Nghia Buis答案中的重构可以进一步进行,使用活动模式和区分性联合

open System.Text.RegularExpressions
let (|EmployeeId|_|) s = 
    match System.Int32.TryParse(s) with   // assuming your id:s are integers
    | (true,int) -> Some(int)
    | _ -> None

let (|Email|_|) s =
    let matches = Regex.Matches(s, ".*?@.*" )
    if matches.Count > 0 then Some matches.[0].Value else None

type IdString = private IdString of string with
    static member Create = 
        function
        | EmployeeId s -> Some s
        | _ -> None
    member this.Value = let (IdString s) = this in s

type Email = private Email of string with
    static member Create = 
        function
        | Email s -> Some s
        | _ -> None
    member this.Value = let (Email s) = this in s

let getByIdAndEmail (id : EmployeeId) (email : Email) =
    // Yay, I know that id and email are valid, non empty and not null
    ["First"]

let getByEmail (email : Email) =
    // email is an email adress, and not any string
    ["Second"]
let getById (id : EmployeeId) =
    // id is really an employeeId.
    ["Third"]

let getEmployees id email =
    // I feel unsafe here, so I have to check
    // Actually I'm being forced to check because if I don't check
    // I won't have valid values to pass to the getByXXX functions above
    match EmployeeId.Create id, Email.Create email with
    | Some reallyId, Some reallyEmail -> getByIdAndEmail reallyId reallyEmail
    | Some reallyId, None -> getById reallyId
    | None, Some reallyEmail -> getByEmail reallyEmail
    | _ -> []
您可能还希望在代码中明确说明如何识别员工

type EmployeeIdentification =  //Let's state explicitly how employees may be identified
    | ById of EmployeeId
    | ByEmail of Email
    | ByIdAndEmail of EmployeeId * Email
type EmployeeIdentification =  //Let's state explicitly how employees may be identified
    | ById of EmployeeId
    | ByEmail of Email
    | ByIdAndEmail of EmployeeId * Email