具有智能构造函数的抽象数据类型的 QuickCheck 任意实例
QuickCheck Arbitrary instance for abstract data type with smart constructor
我是这门语言的新手,正在尝试编写我的第一个重要程序。在途中,我无法创建一个 Arbitrary
实例。然而,我想我的问题是因为我普遍缺乏对组合几种应用和单子类型的理解。因此,我希望从以下内容中获得基本的见解。感谢您的帮助!
我定义了一个 Address
类型和一个智能构造函数,并验证了各个字段,如下所示:
data Address = Address
{ street :: StreetName
, streetExt :: Maybe StreetName
, city :: CityName
, zipCode :: ZipCode
, country :: CC.CountryCode
} deriving (Eq, Show)
mkAddress :: Text -> Maybe Text -> Text -> Text -> Text -> Maybe Address
mkAddress aStreet aStreetExt aCity aZipCode aCountry =
Address <$> mkStreetName aStreet
<*> Just (aStreetExt >>= mkStreetName)
<*> mkCityName aCity
<*> mkZipCode aZipCode
<*> CC.fromMText aCountry
StreetName
、CityName
和 ZipCode
是 Text
的新型包装器,具有验证智能构造函数,仅限制这些字段的最大长度。 streetExt
字段是可选的。国家代码使用Data.ContryCodes.CountryCode
.
整体类型抽象,定义模块只导出智能构造函数,不导出数据构造函数
我现在正在尝试为此类型创建一个 Arbitrary 实例>
instance Arbitrary D.Address where
arbitrary = do
maybeAddress <- D.mkAddress <$> arbitrary -- streetName
<*> return Nothing -- streetExt
<*> arbitrary -- city
<*> arbitrary -- zipCode
<*> elements ["DE", "FR", "AG", "RW"] -- country
return fromJust maybeAddress
但是,我遇到了以下类型检查器错误:
• Couldn't match type ‘Maybe a0 -> a0’ with ‘Gen D.Address’
Expected type: Maybe D.Address -> Gen D.Address
Actual type: Maybe D.Address -> Maybe a0 -> a0
• The function ‘return’ is applied to two arguments,
but its type ‘(Maybe a0 -> a0)
-> Maybe D.Address -> Maybe a0 -> a0’
has only three
从这个错误来看,我认为将生成器包装在 Maybe 中存在一些问题,反之亦然。但即使经过几次 lift
和 join
的实验,我也无法对其进行类型检查。因此,我怀疑我的心智模型在类型的包装方式和生成器单子的返回方式方面存在缺陷。
如果有人能指出我的错误就太好了。
此外,我非常感谢对这种使用抽象类型和智能构造函数的数据建模的评论 - 这是一般推荐的做法,还是会导致像我面临的问题?
非常感谢!
错误信息是这么说的(虽然后面的解释有误导):
The function ‘return’ is applied to two arguments
你有
return fromJust maybeAddress
你想要
return (fromJust maybeAddress)
我是这门语言的新手,正在尝试编写我的第一个重要程序。在途中,我无法创建一个 Arbitrary
实例。然而,我想我的问题是因为我普遍缺乏对组合几种应用和单子类型的理解。因此,我希望从以下内容中获得基本的见解。感谢您的帮助!
我定义了一个 Address
类型和一个智能构造函数,并验证了各个字段,如下所示:
data Address = Address
{ street :: StreetName
, streetExt :: Maybe StreetName
, city :: CityName
, zipCode :: ZipCode
, country :: CC.CountryCode
} deriving (Eq, Show)
mkAddress :: Text -> Maybe Text -> Text -> Text -> Text -> Maybe Address
mkAddress aStreet aStreetExt aCity aZipCode aCountry =
Address <$> mkStreetName aStreet
<*> Just (aStreetExt >>= mkStreetName)
<*> mkCityName aCity
<*> mkZipCode aZipCode
<*> CC.fromMText aCountry
StreetName
、CityName
和 ZipCode
是 Text
的新型包装器,具有验证智能构造函数,仅限制这些字段的最大长度。 streetExt
字段是可选的。国家代码使用Data.ContryCodes.CountryCode
.
整体类型抽象,定义模块只导出智能构造函数,不导出数据构造函数
我现在正在尝试为此类型创建一个 Arbitrary 实例>
instance Arbitrary D.Address where
arbitrary = do
maybeAddress <- D.mkAddress <$> arbitrary -- streetName
<*> return Nothing -- streetExt
<*> arbitrary -- city
<*> arbitrary -- zipCode
<*> elements ["DE", "FR", "AG", "RW"] -- country
return fromJust maybeAddress
但是,我遇到了以下类型检查器错误:
• Couldn't match type ‘Maybe a0 -> a0’ with ‘Gen D.Address’
Expected type: Maybe D.Address -> Gen D.Address
Actual type: Maybe D.Address -> Maybe a0 -> a0
• The function ‘return’ is applied to two arguments,
but its type ‘(Maybe a0 -> a0)
-> Maybe D.Address -> Maybe a0 -> a0’
has only three
从这个错误来看,我认为将生成器包装在 Maybe 中存在一些问题,反之亦然。但即使经过几次 lift
和 join
的实验,我也无法对其进行类型检查。因此,我怀疑我的心智模型在类型的包装方式和生成器单子的返回方式方面存在缺陷。
如果有人能指出我的错误就太好了。 此外,我非常感谢对这种使用抽象类型和智能构造函数的数据建模的评论 - 这是一般推荐的做法,还是会导致像我面临的问题?
非常感谢!
错误信息是这么说的(虽然后面的解释有误导):
The function ‘return’ is applied to two arguments
你有
return fromJust maybeAddress
你想要
return (fromJust maybeAddress)