(This was asked before but it has no answers).
I have a list of countries in a database:
share [mkPersist sqlSettings] [persistLowerCase|
Country
name Text
UniqueCountryName name
deriving Show
|]
And I can show a form to select one of them:
countries = do
rows <- runDB $ selectList [] [Asc CountryName]
optionsPairs $ map (\ r -> (countryName $ entityVal r, entityKey r)) rows
surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
(countryR, countryV) <- mreq (selectField countries) "" Nothing
I know that I should replace the Nothing
in the last line with the desired default value but I still don't get how to do it. Looking at the mreq
and the optionsPairs
signatures my thought was that in this case I should provide a Maybe Option
with the default country but my attempts have raised so many type errors that probably I am quite far from the right answer.
The Yesod book has an example using seems more simple than what I tried to achieve so I am not sure how to extrapolate it.
By the way I am getting the default country from the database so I don't need to hardcode its internal id:
defaultCountry = do
row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
(countryName $ entityVal row, entityKey row)
When I pass it as an argument to mreq
I get the following errors:
Couldn't match type ‘(,) Text’ with ‘HandlerFor site’ Expected type: HandlerFor site (Key record) Actual type: (Text, Key record)
That's on the last line of the of the defaultContry
function ((countryName $ entityVal row, entityKey row)
). I understand that I should take the Key record
from the pair and return it in a HandlerFor site
but at the same time I also get:
Couldn't match expected type ‘Maybe (Key Country)’ with actual type ‘HandlerFor site0 (Key record0)’
In the (countryR, countryV) <- mreq (selectField countries) "" defaultCountry
line. I interprete this as "you are passing me a HandlerFor site0 (Key record0)
but I only accept Maybe (Key Country)
which seems in conflict with the first error...
In the (countryName $ entityVal row, entityKey row)
line I also see:
Couldn't match expected type ‘Entity Country’ with actual type ‘Maybe (Entity Country)’
in the row
argument. I understand that I should extract the Entity Country
from the Maybe
but if I pattern match and pass just the Entity Country
(i. e.: Just (Entity countryId country) -> (countryName $ entityVal (Entity countryId country), entityKey (Entity countryId country)
) I still get the first error.
Thanks in advance.
Alright, this looks like a few type errors. The first
Couldn't match type ‘(,) Text’ with ‘HandlerFor site’ Expected type: HandlerFor site (Key record) Actual type: (Text, Key record)
comes from not using return
in your do
notation to lift the value to the monad:
defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
return (countryName $ entityVal row, entityKey row)
The error on row
Couldn't match expected type ‘Entity Country’ with actual type ‘Maybe (Entity Country)’
is because it's a Maybe
, so let's correct that
defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
Just row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
return (countryName $ entityVal row, entityKey row)
Now that defaultCountry
is a good monad, you should be able to use it in your other code. But be careful of that third error
Couldn't match expected type ‘Maybe (Key Country)’ with actual type ‘HandlerFor site0 (Key record0)’
You need to unwrap the value from the HandlerFor
monad, and rewrap it in a Maybe
surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
(defaultName, defaultKey) <- defaultCountry -- (defaultName, defaultKey) :: (Text, Key record)
(countryR, countryV) <- mreq (selectField countries) "" (Just defaultKey)