我是语言新手,想写第一个非平凡的程序。在写的过程中,我卡在了创建一个 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里面封装Generator有问题,或者相反。但即使经过几次实验 lift
和 join
我无法让它进行类型检查。因此,我怀疑我的心智模型对类型的封装方式和生成器单体的返回方式存在缺陷。
如果有人能指出我的错误,那将是非常好的.另外,我非常感谢对这种使用抽象类型和智能构造器的数据建模的评论--这是一般推荐的做法,还是会导致像我所面临的问题?
非常感谢!我是一个新的语言爱好者,正在尝试使用抽象类型和智能构造器来进行数据建模。
错误信息说的很清楚(虽然后续的解释是误导性的)。
The function ‘return’ is applied to two arguments
你有
return fromJust maybeAddress
你想
return (fromJust maybeAddress)