如何对F#记录进行参数验证

Car*_*ngo 18 f# constructor record

F#可以很容易地定义类型

type coords = { X : float; Y : float }
Run Code Online (Sandbox Code Playgroud)

但是如何在不进入更详细的类定义语法的情况下为构造函数定义约束/检查参数?例如,如果我想从(0,0)开始coords或抛出异常.

此外,如果我将我的定义更改为类,我需要实现Equals()等所有我不想要的样板代码(以及我在C#中试图摆脱的那些).

Dan*_*iel 18

您可以将实现设为私有.您仍然可以获得结构上的平等,但是会丢失直接的字段访问和模式匹 您可以使用活动模式恢复该功能.

//file1.fs

type Coords = 
  private { 
    X: float
    Y: float 
  }

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Coords =
  ///The ONLY way to create Coords
  let create x y =
    check x
    check y
    {X=x; Y=y}

  let (|Coords|) {X=x; Y=y} = (x, y)

//file2.fs

open Coords
let coords = create 1.0 1.0
let (Coords(x, y)) = coords
printfn "%f, %f" x y
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我的直觉告诉我这是非常复杂的,而不是一个非常典型的制作类型的方法?我想创建一个类并实现Equals更可取..或强制我的程序中的所有类型都是通过一些通用的create方法构造的? (3认同)
  • 这是一个很好的解决方案丹尼尔.希望我能想到它. (2认同)

stm*_*max 9

有一系列被称为与类型设计F#的乐趣和利润.在"强制使用构造函数"一节中,它建议使用构造函数 - 这是在实例化类型之前验证的位置.为了防止人们直接实例化类型,它建议使用命名约定或签名文件.

您可以通过Google搜索"域驱动设计f#"找到更多相关文章和示例.

请注意,我来自C#/没有将F#应用到我们的域层(但是;)我无法确定任何推荐的方法如何在更大的项目中运行.在这个勇敢的新世界中,有些事情看起来确实不同.