让我在C#上有这样的代码。如何用F#在函数样式中重写此早午餐逻辑?我应该使用什么模式匹配?主动模式匹配?区分工会?
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);
}
}
F#
let GetEmployees (id:string)(email:string) =
match (id,email) with
...
答案 0 :(得分:6)
我认为这已经足够了:
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#类型系统的功能及其简洁的语法,我建议您进一步编写一种新的字符串类型,以确保其内容不为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
| _ -> []
答案 1 :(得分:1)
可以使用主动模式和区分联合来进一步进行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