我有12个值的记录。有一些值无效的组合,所以我希望构造函数检查这一点。我只知道如何制作带有参数列表的构造函数,但是对于12个值来说这不是很漂亮。因此,我想在构造它之后使用该值时使用记录语法。
如何在构造函数中强制执行约束并仍然使用记录语法?
答案 0 :(得分:5)
我将以更详细的方式发布我的第一条评论,也许你会发现这很好。
首先,让我们假设您的数据或多或少看起来像这样:
data MyBigData = MyBigData {
a :: ...
b :: ...
...
z :: ...
}
实际上,当用智能构造函数替换时,你不能对这个问题做很多事情。
但是,假设你的库函数看起来或多或少是这样的:
libFun :: MyBigData -> Result
我提出以下解决方案。创建包装类型:
newtype ValidData = ValidData MyBigData
不要导出其构造函数。将您的功能更改为:
libFun :: ValidData -> Result
libFun (ValidData d) = ...
并将验证逻辑放在一个函数中:
validate :: MyBigData -> Maybe ValidData
现在,当调用validate
时,您可以使用记录语法,但如果您不首先验证它,则无法在任何实际期望它处于相干状态的函数中使用此数据。
input = validate $ MyBigData { ... }
case input of:
Just d -> libFun d
Nothing -> ...
当然,在这种情况下,validate
也可以返回Either
,或者如果您需要,也可以单独行动。
答案 1 :(得分:2)
我会使用Bartek Banachewicz建议将辅助数据类型Blueprint
与开放和未经验证的构造函数以及ActualData
智能构造函数fromBluePrint :: Blueprint -> ActualData
一起使用,并结合一个简单的函数
section :: ActualData -> Blueprint
只是'抛弃'验证(意味着fromBlueprint . section
是ActualData
- 部分上的标识,another name是右逆< / em>的)
现在,您可以使用viewPatterns并编写类似
的代码 x :: ActualData
x = fromBlueprint $ Blueprint {a=1, b="baz",...}
f :: ActualData -> Int
f (section -> Blueprint{a=x}) = 2*x
在构造ActualData
类型的值时使用记录语法,并在ActualData
上定义函数时使用模式(或者在[ActualData]
等更复杂的类型上使用,因为视图可以嵌套)