2014-01-06 18 views
3

我想爲runFormPost正在生成的小部件(Html表單)提供一些上下文。我認爲我可以簡單地將結果粘貼到一個Tuple中,並將其與我的哈姆雷特的背景和模式相匹配,但由於Handler Monads的原因,它變得具有挑戰性。將runFormPost小部件放入一個元組

我有一個單子窗體具有以下類型簽名:

myForm :: ModelId -> Model -> Html -> MForm Handler (FormResult MyData, Widget) 
myForm rid rec extra = do 
    -- whamlet code here 

我渲染內forM一系列的表格,並使用我的哈姆雷特文件小部件的列表。它一切正常。

widgets <- forM rs' $ \(Entity rid rec) -> 
      runFormPost $ myForm rid rec 

現在,我想向每個小部件添加一些數據並將其作爲元組返回。對於這個簡單的例子,我們假設我想添加一個String。我想下面的代碼,當我嘗試在我的哈姆雷特文件中使用它,它不會編譯(編譯它,如果我沒有在我的哈姆雷特文件中使用widgets列表)

widgets <- forM rs' $ \(Entity rid rec) -> 
      return ("Test", runFormPost $ myForm rid rec) 

在我的哈姆雷特文件,我試着這樣的事情(x是我的字符串上下文):

$forall (x,((res,widget), enctype)) <- widgets 
    <div> 
     <form method=post [email protected]{HandlerR hId} enctype=#{enctype}> 
      ^{widget} 

我得到以下錯誤:使用fmap

Couldn't match expected type `((t0, a1), a0)' 
      with actual type `Handler ((FormResult MyData, Widget), Enctype)' 
Expected type: [(t1, ((t0, a1), a0))] 
    Actual type: [(t1, 
       Handler ((FormResult MyData, Widget), Enctype))] 
In the second argument of `Data.Foldable.mapM_', namely `widgets' 

到目前爲止,我已經嘗試和liftM裏面forM or map但我不斷收到類似的錯誤。我也嘗試在我的模式匹配中投擲Handler,它給了我一個錯誤,說Handler不在範圍內。

有關如何將一些附加信息附加到窗口小部件並在我的哈姆雷特文件中重新使用它的想法?

謝謝!

+1

這是我第一次的猜測:問題是,'runFormPost'產生其被包裹在一個單子,'Handler'結果在這種情況下:'widgets ::(String,Handler((FormResult MyData,Widget),Enctype)'。因此,你應該首先使用你定義的解包版本'widgets'來添加你的附加信息。版本的widgets ::((FormResult MyData,Widget),Enctype)',你可以添加'let widgetsWithInfo = map(\ w - >(「test」,w))widgets'這一行。在你的hamlet文件中,你應該使用'widgetsWithInfo ::(String,((FormResult MyData,Widget),Enctype))''。 – ichistmeinname

+0

@ichistmeinname它很好用......謝謝!您能否將此作爲回覆發佈,以便我可以接受您的回答?另外,如果你能幫助我理解爲什麼使用類似'fmap'的東西不起作用,那將會很棒。例如,如果我做'fmap(\ x - >(「Test」,x))runFormPost $ myForm rid rec'不會將fmap解包爲runFormPost並將其打包回來?這是因爲堆疊Monads嗎? – Ecognium

回答

2

問題是runFormPost產生的結果是在這種情況下包裝在一個monad中,Handler

widgets :: (String, Handler ((FormResult MyData, Widget), Enctype) 

因此,您應該首先使用您定義的解包版本小部件來添加附加信息。使用的widgets :: ((FormResult MyData, Widget), Enctype)你的第一個版本,可以再加入行

let widgetsWithInfo = map (\w -> ("test", w)) widgets 

在你的小村莊文件,你應該再嵌入widgetsWithInfo :: (String, ((FormResult MyData, Widget), Enctype)

對於您的其他問題:您對fmap的意圖對我來說似乎是正確的,但是(如果它不只是一個錯字)您的表達是括號不正確。要應用fmaprunFormPost $ myForm rid rec的結果,所以你必須parenthesise該子表達式:

fmap (\x -> ("Test", x)) (rumformPost $ myForm rid rec) 
相關問題