【问题标题】:Monad Transformer for Halogen Components用于卤素元件的 Monad 变压器
【发布时间】:2015-06-04 16:29:18
【问题描述】:

我正在尝试找出在 Halogen 组件包含的 monad 上使用转换器的方式。

我想通过带有 Config 记录的 ReaderT 扩展 intro example,在这种情况下可用于使字符串可配置,但在将它们放在一起时我迷失了。

假设我们这样定义我们的配置:

-- | Global configuration
newtype Config = Config { toggleText :: String
                        , onText :: String
                        , offText :: String
                        }

然后我们的ui 函数将从

forall m eff. (Monad m) => Component m Input Input

forall m (Monad m) => Component (ReaderT Config m) Input Input.

为了评估我们的 main 函数,我们将使用 hoistComponent 将其变回原来的形式:

main = do
  let config = Config { toggleText: "Toggle Button"
                      , onText: "On"
                      , offText: "Off"
                      }
  Tuple node _ <- runUI $ hoistComponent (runReaderT config) ui
  appendToBody node

到目前为止,我不确定这是否有意义,但假装它有意义,下一步就是我正在努力的地方。在理想的世界中,我的 ui 函数可以让我做这样的事情:

ui :: forall m eff. (Monad m) => Component (ReaderT Config m) Input Input
ui = render <$> stateful (State { on: false }) update
  where
  render :: State -> H.HTML (ReaderT Config m Input)
  render (State s) = do
    (Config conf) <- ask
    return $ H.div_ [ H.h1_ [ H.text conf.toggleText ]
                    , H.button [ A.onClick (A.input_ ToggleState) ]
                               [ H.text (if s.on then conf.onText else conf.offText) ]
                    ]

  update :: State -> Input -> State
  update (State s) ToggleState = State { on: not s.on }

但我最终遇到了一连串的统一错误,不知道从哪里开始。显然,ask 的内部使用不能像这样工作,因为我需要将它提升到 HTML 上下文中,但我什至不确定这是否可能。

如果有人可以指导我了解这里的类型并告诉我这种通用方法是否明智,那就太好了。一个完整(非编译)的例子是on GitHub。 I18n 应仅在此处用作阅读器的简单示例使用。

【问题讨论】:

    标签: monad-transformers purescript halogen


    【解决方案1】:

    monad m 是事件处理程序的 monad。 HTML 文档本身无法访问您的 Reader monad 中的配置。

    如果您希望您的事件处理程序能够访问某些配置对象,您可以使用 Reader,并且您必须将 A.input_ 的使用替换为 Reader monad 中的操作。

    要做你想做的事,你可能想要更像MonadReader Config m =&gt; m (Component _ _ _)的东西,其中组件本身取决于配置。

    【讨论】:

    • 感谢 Phil,这消除了我对事件处理程序和内部 monad 用例的误解之一。如果我想在 Config 对象上使用MonadReader,那么我是否必须实现instance SF1ReaderT :: (Monad m) =&gt; MonadReader r (SF1 req) where ...
    • 嗯,至关重要的是,SF1 不是Monad,因为它的Apply 实例是如何工作的。如果您想将配置对象与信号函数一起使用,我会诚实地将其作为参数传递。
    • 这可以解释No instance found for Prelude.Monad r13 中的r13 所指的内容。谢谢你这么有耐心,我想我一直试图在这里一次学习太多东西。我现在将手动传递它。 :)
    猜你喜欢
    • 1970-01-01
    • 2018-04-18
    • 2018-09-11
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    相关资源
    最近更新 更多