在Yesod子网站表单中使用选项字段时出错

时间:2014-11-18 12:45:36

标签: haskell yesod yesod-forms

我正在尝试在子网站表单中使用selectFieldList但是我收到以下错误:

Couldn't match type 'IO' with 'HanderT master IO'

我在使用以下代码段时遇到此问题,其中子网站名为TestSub(此子网站与主网站分开):

类型:

type TestHandler a = forall master. Yesod master
    => HandlerT TestSub (HandlerT master IO) a

type Form a = forall master. Yesod master
    => Html -> MForm (HandlerT TestSub (HandlerT master IO)) (FormResult a, WidgetT TestSub IO ())

Form&处理程序:

testForm :: Form (Text, Int)
testForm = renderBootstrap3 BootstrapBasicForm $ (,)
    <$> areq textField (bfs MsgText) Nothing
    <*> areq (selectFieldList [(MsgFirst, 1), (MsgSecond, 2)]) (bfs MsgSelect) Nothing

getTestHome :: TestHandler Html
getTestHome = do
    (formWidget, _) <- generateFormPost testForm
    defaultLayoutSub $ do
        setTitleI MsgTest
        [whamlet|^{formWidget}|]

当select字段替换为例如intField时,表单和处理程序按预期工作。在Hoogle上查找selectFieldList时,我发现选项字段(选择,广播,复选框)具有不同的签名(显示在下方),然后是“普通”字段。我怀疑这个区别是问题,但是没有找到解决办法而不必全部实现选项字段。

选项字段签名:

selectFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg)
                => [(msg, a)]
                -> Field (HandlerT site IO) a

正常字段签名:

intField :: (Monad m, Integral i, RenderMessage (HandlerSite m) FormMessage)
         => Field m i

有没有办法让选项字段在子网站上下文中工作,而不重新实现它们?

1 个答案:

答案 0 :(得分:1)

通常最好通过调用lift在主站点而不是子站点中运行表单。您还需要稍微修改您的类型同义词以匹配,但基本想法是替换:

(formWidget, _) <- generateFormPost testForm

(formWidget, _) <- lift $ generateFormPost testForm

修改

我仍然推荐上述方法。但是,要获得您要求的替代品,请将您的类型同义词更改为:

type Form a =
   Html -> MForm (HandlerT HelloSub IO) (FormResult a, WidgetT HelloSub IO ())

然后使用liftHandlerT

liftHandlerT $ generateFormPost testForm

请注意,这不是设计使用子网站的方式,所以当你继续前进时,你可能会遇到更多的摩擦。

关于主翻译:你绝对可以利用它们,你只需要按照RenderMessage master MessageDataType的约束。这就是整个地方FormMessage使用的内容。

<强> EDIT2

您可能会发现另一个有用的咒语:

defaultLayoutSub $ liftWidgetT widget