在Haskell数据构造函数中输入检查

qua*_*dev 13 validation constructor haskell

如何向Haskell数据构造函数添加输入检查?让我说我有

import Data.Time.Calendar

data SchedulePeriod = SchedulePeriod { startDate :: Day
    , endDate :: Day
    , accrualStart :: Day
    , accrualEnd :: Day
    , resetDate :: Day
    , paymentDate :: Day
    , fraction :: Double }
    deriving (Show)
Run Code Online (Sandbox Code Playgroud)

我想强加一个约束startDate < endDate.有没有办法在不创建抽象数据类型的情况下执行此操作?

ehi*_*ird 17

标准方法是使用智能构造函数,在创建值之前检查前置条件,并且不导出它使用的实际构造函数.当然,正如你所说,这是创建一个抽象数据类型.

没有智能构造函数实现这一目标的唯一方法是真正邪恶的类型系统hackery(你将无法使用标准Day类型).

  • @quant_dev如果您不想要抽象数据类型的原因是您可以在构造函数上进行模式匹配,那么您可以执行智能构造函数的双重操作并实现智能析构函数(类似于`maybe`和`both`). (3认同)

Gab*_*lez 13

接受ehird的回答.我只是写这个,所以我可以解释我在评论中提到的智能析构函数,我无法在评论中解释.

假设您有类型:

data T x y z = A | B x | C y z
Run Code Online (Sandbox Code Playgroud)

ehird已经解释了如何抽象掉构造函数,这只是为了提供"智能"构造函数.就像你提到的,这需要隐藏构造函数,然后你不能使用它们来模式匹配.但是,您可以使用"智能"析构函数来解决此问题,这相当于对每个可能的构造函数进行模式匹配.

为了解释这一点,让我们首先介绍如果构造函数被暴露,我们如何编写类型为T的函数:

myFunction :: T x y z -> d
myFunction t = case t of
    A     -> f1
    B x   -> f2 x
    C y z -> f3 y z
Run Code Online (Sandbox Code Playgroud)

我们从函数的类型签名知道类型的f1,f2以及f3必须是:

f1 :: d
f2 :: x -> d
f3 :: y -> z -> d
Run Code Online (Sandbox Code Playgroud)

所以,如果我们要推广myFunction是一个聪明的析构函数,我们只是传递f1,f2f3作为参数传递给它:

smartDestructor :: d -> (x -> d) -> (y -> z -> d) -> t -> d
smartDestructor f1 f2 f3 t = case t of
    A     -> f1
    B x   -> f2 x
    C y z -> f3 y z
Run Code Online (Sandbox Code Playgroud)

因此,如果您导出smartDestructor,那么人们基本上可以与您的类型进行模式匹配,而无需访问构造函数.

如果您之前使用过maybe或者either函数,那么您已经使用了智能析构函数,尽管在这些情况下构造函数不是隐藏的,因此它们主要作为便利函数提供:

maybe :: b -> (a -> b) -> Maybe a -> b
maybe f1 f2 m = case m of
    Nothing -> f1
    Just  a -> f2 x

either :: (a -> c) -> (b -> c) -> Either a b -> c
either f1 f2 e = case e of
    Left  a -> f1 a
    Right b -> f2 b
Run Code Online (Sandbox Code Playgroud)

在您的情况下,智能析构函数的目的只是为了隐藏构造函数而不暴露构造函数.

  • @quant_dev我刚刚了解到"智能析构函数"有一个更好的名称.它被称为"教会编码"数据类型,它指的是任何数据类型都可以表示为函数,这种函数编码称为"教会编码".有关一个非常好的解释,请查看此链接:http://web.archiveorange.com/archive/v/nDNOvgzSRV6TNq8KhCgZ (3认同)