简体   繁体   English

如何将约束或验证/条件验证(在类型变量上)放入? 在这里:如何强制Radius> 0?

[英]How to put constraints or validations / conditional validations (on type variables)? Here: How to force Radius > 0?

If the constraint has to be set that the Radius of any Circle created must be greater than zero ( Radius > 0 ). 如果必须设置约束,则创建的任何圆的半径必须大于零(半径> 0)。 How to do it? 怎么做?

data Point = Point Float Float deriving (Show)  
data Radius = Radius Float deriving (Show)  
data Shape = Circle Point Radius deriving (Show)
surface :: Shape -> Float  
surface (Circle _ (Radius r)) = pi * r ^ 2  

If convenient, please give few more examples for how one can set constraint / validations in various scenarios. 如果方便的话,请给出更多示例,说明如何在各种情况下设置约束/验证。 Eg data phone can have regex or specific set of starting number (area code or country code etc.). 例如,数据电话可以具有正则表达式或特定的起始号码集(区号或国家/地区代码等)。

The simplest way to achieve validation on the fields of data types is not to export from the module the value constructors, and define and export instead functions that perform the required checks before actually constructing and returning the object using the hidden value constructor. 在数据类型的字段上实现验证的最简单方法是,不从模块中导出值构造函数,而是定义和导出在使用隐藏的值构造函数实际构造和返回对象之前执行所需检查的函数。

A simple example with two possible ways to report the error: 一个简单的示例,其中包含两种可能的报告错误的方法:

module MyModule
( Radius  -- we do not export value constructors
, radius
, radius'
) where

data Radius = Radius Float deriving (Show)

radius :: Float -> Maybe Radius
radius r | r > 0     = Just (Radius r)
         | otherwise = Nothing

radius' :: Float -> Radius
radius' r | r > 0     = Radius r
          | otherwise = error "negative radius"

In this way, the users of your module will only be able to create new values only through the functions you personally defined, and not through the value constructors that would enable them to skip all checks. 这样,模块的用户只能通过您自己定义的函数创建新值,而不能通过使他们跳过所有检查的值构造函数来创建新值。

If you want something a little more fun than Riccardo's solution, you could use lenses as your interface to the type. 如果您想要比Riccardo的解决方案有趣的东西,可以将镜头用作该类型的界面。 You can do this currently with fclabels , although there isn't a way to distinguish failure on an outer constructor from failure on the inner value you're trying to validate. 您目前可以使用fclabels进行此操作 ,尽管没有办法将外部构造函数的故障与您要验证的内部值的故障区分开。

I've also written an experimental lens lib that attempts to address that use-case in a more structured way, but I can't really recommend it at this stage. 我还写了一个实验性的镜头库 ,试图以一种更加结构化的方式解决该用例,但是我目前不能真正推荐它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM