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