记录语法:验证构造函数中的内容

时间:2016-04-22 20:14:53

标签: haskell

我有12个值的记录。有一些值无效的组合,所以我希望构造函数检查这一点。我只知道如何制作带有参数列表的构造函数,但是对于12个值来说这不是很漂亮。因此,我想在构造它之后使用该值时使用记录语法。

如何在构造函数中强制执行约束并仍然使用记录语法?

2 个答案:

答案 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 . sectionActualData - 部分上的标识,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]等更复杂的类型上使用,因为视图可以嵌套)