我是这门语言的新手,正在尝试编写我的第一个非平凡的程序。在创建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
。
总体类型是抽象的,定义模块只导出智能构造函数,而不导出数据构造函数。
我现在正试图为这种类型创建一个任意实例>
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中包装Generator存在一些问题,或者相反。但即使经过几次实验lift
和join
,我也无法对其进行类型检查。因此,我怀疑我的心理模型在如何包装类型以及如何返回生成器monad方面存在缺陷。
如果有人能指出我的错误就太好了。此外,我非常感谢对这种使用抽象类型和智能构造函数的数据建模类型的评论——这是一般推荐的做法,还是会导致我面临的问题?
非常感谢!
错误消息显示(尽管随后的解释具有误导性(:
The function ‘return’ is applied to two arguments
你有
return fromJust maybeAddress
你想要
return (fromJust maybeAddress)