c# - How to build F# type fulfilling business rules?
问题描述
I´m trying to build a type in F#, where when I get an object of that type I can be sure it´s in a valid state.
The type is called JobId
and it just holds a Guid
.
The business rule is: It must be a Guid - but no empty Guid.
I´ve already implemented the type in C# but now I would like to port it to a F# class library.
That´s the C# type:
public sealed class JobId
{
public string Value { get; }
private JobId(string value)
=> Value = value;
public static JobId Create()
=> new JobId(Guid.NewGuid().ToString("N"));
public static Option<JobId> Create(Guid id)
=> id == Guid.Empty
? None
: Some(new JobId(id.ToString("N"));
public static Option<JobId> Create(string id)
{
try
{
var guid = new Guid(id);
return Create(guid);
}
catch (FormatException)
{
return None;
}
}
}
So how do I build that in F#? Thanks!
Update 1:
I tried to implement it as discriminated union type like this:
type JobId =
| JobId of string
But the problem is, that I can´t define any business rules with that approach.
So the final question is: How to ensure that the string
in JobId
ist in a
certain format?
解决方案
I've adapted Tomas' answer to use a DU instead of a class to preserve proper equality and comparison, allowing JobId
to work as expected as a grouping key, for example.
[<AutoOpen>]
module JobId =
open System
type JobId = private JobId of string with
static member Create() = JobId(Guid.NewGuid().ToString("N"))
static member Create(id:Guid) =
if id = Guid.Empty then None
else Some(JobId(id.ToString("N")))
static member Create(id:string) =
try JobId.Create(Guid(id))
with :? FormatException -> None
You have to put the type inside a module and then you can't access the DU constructor directly outside of that module:
JobId.Create (System.Guid.NewGuid()) // Some (JobId "1715d4ae776d441da357f0efb330be43")
JobId.Create System.Guid.Empty // None
JobId System.Guid.Empty // Compile error
推荐阅读
- excel - 如何获取函数“PMT”的值 - (函数的算法)
- mysql - 从一个表中选择行并根据另一个表中的行调整值
- npm - npm install bootstrap 和 npm install bootstrap --save 有什么区别
- javascript - 用 PHP 和 AJAX 编写代码来记录用户的屏幕尺寸
- reactjs - 即使前端断开连接,如何保持任务在后端运行?
- excel - 使用帮助列对数据进行分组/排序
- node.js - 使用 Let's Encrypt 证书通过 HTTPS 访问 CouchDB 时,节点无法验证第一个证书
- regex - 正则表达式有时有空格有时没有的字符串
- javascript - Vue在页面加载时滚动到顶部
- php - 如何为消息传递应用程序设计数据库架构?