我有一个处理添加和编辑的地址表单(如果添加则为Nothing,如果编辑则为Just Address)。到目前为止,我已经用一些项目对州和国家的选择进行了硬编码。
addressForm :: Monad m => Maybe Address -> [Address] -> Form Text m Address
addressForm a addrs =
Address
<$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
<*> "name" .: string (fmap name a)
<*> "street" .: string (fmap street a)
<*> "city" .: string (fmap city a)
<*> "state" .: choiceWith stateChoices (fmap state a)
<*> "country" .: choiceWith countryChoicesRequired (fmap country a)
<*> "zipcode" .: string (fmap zipcode a)
stateChoices :: [(Text, (Maybe String, Text))] -- (htmlValue, (realValue, labelValue))
stateChoices = [("ON", (Just "ON", "Ontario")), ("NE", (Just "NE", "Nebraska"))]
countryChoicesRequired :: [(Text, (String, Text))]
countryChoicesRequired = [("CA", ("CA", "Canada")), ("US", ("US", "United States of America"))]
现在我想从数据库中检索州和国家列表。我可以将状态/国家/地区列表传递给表单,就像我已经使用地址列表一样,但此表单也是3或4个其他表单(新广告客户表单,新客户表单等)的子表单。而且我不需要表格之外的州/国家列表,就像我对地址列表一样。
这是我刚刚添加了获取国家/地区信息的新表单:
addressForm' :: (HasPostgres p, Monad m) => Maybe Address -> [Address] -> p (Form Text m Address)
addressForm' a addrs = do
countries <- countryChoices'
return $ Address
<$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
<*> "name" .: string (fmap name a)
<*> "street" .: string (fmap street a)
<*> "city" .: string (fmap city a)
<*> "state" .: choiceWith stateChoices (fmap state a)
<*> "country" .: choiceWith countries (fmap country a)
<*> "zipcode" .: string (fmap zipcode a)
data Region = Region
{ code :: String
, fullName :: String
}
countryChoices' :: HasPostgres m => m [(Text, (String, Text))]
countryChoices' = do
countries <- getCountries
return $ abbrToChoice countries
abbrToChoice :: [Region] -> [(Text, (String, Text))]
abbrToChoice regions =
map (\ a -> ((pack $ code a), (code a, (pack $ fullName a)))) regions
这是调用它的处理程序:
editAddressH :: ([(T.Text, Splice AppHandler)] -> AppHandler ()) -> Addr.Address -> Maybe Int64 -> AppHandler ()
editAddressH renderer a userId = do
addresses <- Addr.list userId
(view, result) <- runForm "form" $ Addr.addressForm' (Just a) addresses -- line 233
case result of
Just x -> do
r <- Addr.edit x -- line 236
case r of
_ -> renderer [("success", showContents), ("dfForm", hideContents)]
Nothing -> renderer $ ("success", hideContents) : ("addressList", addressScriptSplice addresses) : phoneSplices ++ digestiveSplices view
我得到的错误是:
src/Site.hs:233:44:
No instance for (HasPostgres
(digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
(Handler App App) v0 (Handler App App)))
arising from a use of `Addr.addressForm''
Possible fix:
add an instance declaration for
(HasPostgres
(digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
(Handler App App) v0 (Handler App App)))
In the second argument of `($)', namely
`Addr.addressForm' (Just a) addresses'
In a stmt of a 'do' expression:
(view, result) <- runForm "form"
$ Addr.addressForm' (Just a) addresses
In the expression:
do { addresses <- Addr.list userId;
(view, result) <- runForm "form"
$ Addr.addressForm' (Just a) addresses;
case result of {
Just x -> do { ... }
Nothing
-> renderer
$ ("success", hideContents)
: ("addressList", addressScriptSplice addresses)
: phoneSplices ++ digestiveSplices view } }
src/Site.hs:236:40:
Couldn't match expected type `Addr.Address'
with actual type `digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
m0 Text m0 Addr.Address'
Expected type: Addr.Address
Actual type: Form Text m0 Addr.Address
In the first argument of `Addr.edit', namely `x'
In a stmt of a 'do' expression: r <- Addr.edit x
答案 0 :(得分:5)
看起来您需要monadic功能。它可能看起来像这样:
addressForm :: Monad m => Maybe Address -> [Address] -> Form Text m Address
addressForm a addrs = monadic $ do
stateChoices <- getStatesFromDB
countryChoices <- getCountriesFromDB
return $
Address
<$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
<*> "name" .: string (fmap name a)
<*> "street" .: string (fmap street a)
<*> "city" .: string (fmap city a)
<*> "state" .: choiceWith stateChoices (fmap state a)
<*> "country" .: choiceWith countryChoices (fmap country a)
<*> "zipcode" .: string (fmap zipcode a)