我正在试图弄清楚我可以在Halogen组件所包含的monad上使用变换器。
我想通过带有Config记录的ReaderT扩展intro example,在这种情况下可以用来使字符串可配置,但是当我把它放在一起时我很遗憾
假设我们像这样定义我们的Config:
-- | 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
。
为了评估我们的主要功能,我们然后使用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应该只是在这里使用Reader的简单示例。
答案 0 :(得分:3)
monad m
是事件处理程序的monad。 HTML
文档本身无法访问Reader
monad中的配置。
如果您希望事件处理程序可以访问某些配置对象,则可以使用Reader
,并且必须使用A.input_
monad中的操作替换Reader
的使用
要做你想做的事,你可能想要更像MonadReader Config m => m (Component _ _ _)
的东西,其中组件本身取决于配置。