Я новичок в языке, пытаюсь написать свою первую нетривиальную программу. По дороге я застрял в создании экземпляра Arbitrary
. Тем не менее, я полагаю, что мой вопрос следует пунктам из-за моего общего непонимания, составляющего несколько аппликативных и монадических c типов. Следовательно, я надеюсь получить фундаментальное понимание следующего. Спасибо за вашу помощь!
Я определил тип 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 или наоборот. Но даже после нескольких экспериментов lift
и join
я не могу заставить его проверить тип. Таким образом, я подозреваю, что моя ментальная модель имеет недостатки в том, как обертываются типы и как возвращаются генераторные монады.
Было бы замечательно, если бы кто-то мог указать на мою ошибку. Кроме того, я был бы очень признателен за комментарий к этому типу моделирования данных с использованием абстрактных типов и умных конструкторов - это общая рекомендуемая практика или она приводит к проблемам, подобным той, с которой я сталкиваюсь?
Большое спасибо !