Haskell 使用reflect.GI.Gtk,如何在事件中使用和强制评估动态

Haskell 使用reflect.GI.Gtk,如何在事件中使用和强制评估动态,haskell,reactive-programming,gtk3,reflex,Haskell,Reactive Programming,Gtk3,Reflex,使用reflex-gi-gtk-0.2.0.0时 我可以从事件中访问动态文件: submitButtonE4 <- eventOnSignal submitButton #clicked ( do let processDyn dynCompany = do case dynCompany of Just company -> do

使用reflex-gi-gtk-0.2.0.0时 我可以从事件中访问动态文件:

submitButtonE4 <- eventOnSignal submitButton #clicked 
          (
            do
             let processDyn dynCompany = do
                   case dynCompany of 
                     Just company -> do 
                       path <- chartAnnualROA company fileOptions800x600 --generateChart company
                       Gtk.imageClear chartImage
                       Gtk.set chartImage  [#file := T.pack defaultReportPath]
                       --return x -- path 
                       case T.null $ T.pack path of
                         True ->   return "" --dynCompany
                     Nothing -> return "" --  dynCompany 
             return $ ffor  maybeCompanyDyn processDyn
            >>= )
现在我可以把它沉下去,引起评估

sink submitClickStatusLabel[#label:==ffor submitButtonE(T.pack.show)]

在使用第一种方法时,我无法找到任何强制评估的方法。我如何在不使用其他小部件的情况下强制进行评估


谢谢

我想你的大部分麻烦来自这样一个事实,你想在
事件信号
中做大量的工作。这个地方并不打算对您的业务逻辑进行实际的繁重工作,也没有为您提供适当的上下文来有效地处理反应式价值观,如您当前所经历的
Dynamic
s

eventOnSignal*
函数系列的实际使用情况是为无功网络获取基本输入。按钮提供的输入不包含任何实际信息。它仅在单击按钮时提供信息。对于这种情况,您通常不希望直接使用
eventOnSignal
,而是希望使用
eventOnSignal0
,所以让我们这样做:

submitClickedE <- eventOnSignal0 submitButton #clicked
这里的赋值类型为
processDynD::Dynamic t(IO(可能是公司))
。如您所见,
IO
尚未执行。幸运的是,
reflection
提供了一个在反应值内执行
IO
操作的操作,称为
performEvent::Event t(Performable ma)->m(Event ta)
。这种类型有两个方面不太符合我们目前的需要。首先,它希望执行的monad是一个
可执行的m
,而我们有
IO
,但我们马上就会谈到这一点。第二个也是更紧迫的问题是,
performEvent
预期的是
事件,而不是
动态事件。这是有意义的,因为您不能连续执行
IO
操作。您必须决定何时执行
IO
操作


a单击
submitButton
时,您希望执行IO的UI。因此,我们需要一个
事件
,该事件在
submitClickedE
激发时激发,但它应该激发
processDynD
中的当前值。这样做被称为“使用
事件对
行为
进行采样”
,可以使用操作符
(这是基于Kritzefitz的答案的新版本

用于从组合框中选择公司的事件,与以前相同

companySelectionE <- eventOnAttribute companyCboxBoxEntryWidget #text
submitClickedE现在使用EventSignal0而不是EventSignal

    submitClickedE <- eventOnSignal0 submitButton #clicked

submitlickede谢谢,这解释了很多想法。我用新代码发布了一个答案。如果你对
performEvent
的结果不感兴趣,但只想执行
IO
,你也可以使用
performEvent\uu
。说它稍微快一点。你也不需要绑定
perfo的结果如果您不打算使用其结果,请将rmEvent
更改为名称。总之,我会将您的最后一行更改为
performEvent\uu$runGtk generatechart
。好的。编译并运行良好。
let processDynE = current processDynD <@ submitClickedE
processedCompany <- performEvent $ runGtk <$> processDynE
sink submitClickStatusLabel [#label :== T.pack . show <$> processedCompany]
companySelectionE <- eventOnAttribute companyCboxBoxEntryWidget #text
companySelectionB <- hold Nothing $ ffor companySelectionE (`Map.lookup` companyMap) 
    let 
      generateChart company = do
        case company of 
          Just companyJ -> do 
            chartAnnualROA companyJ fileOptions800x600 
            Gtk.imageClear chartImage
            Gtk.set chartImage  [#file := T.pack defaultReportPath]
            return () 
          Nothing -> return () 
    submitClickedE <- eventOnSignal0 submitButton #clicked
    let generateChartB = generateChart <$> companySelectionB
     let generateChartE = generateChartB <@ submitClickedE 
    processedCompany <- performEvent $ runGtk <$> generateChartE
    companySelectionE <- eventOnAttribute companyCbox #text
    companySelectionB <- hold Nothing $ ffor companySelectionE (`Map.lookup` companyMap)
    let 
        generateChart company = do
          case company of 
            Just companyJ -> do 
              chartAnnualROA companyJ fileOptions800x600 
              Gtk.set chartImage  [#file := T.pack defaultReportPath]
              return () 
            Nothing -> return () 
         
    submitClickedE <- eventOnSignal0 submitButton #clicked
    let generateChartB = generateChart <$> companySelectionB
    let generateChartE = generateChartB <@ submitClickedE
    processedCompany <- performEvent $ runGtk <$> generateChartE