2016-12-26 48 views
1

我在Haskell项目中使用monad变压器RWST。下面是我的源代码:在Haskell中使用monad变压器RWST

type HSL a = RWST HBConfig [HBLog] a IO a  

runScript :: (HLanguage a, BuilderHSL a) 
      => HBConfig 
      -> HSL a 
      -> String 
runScript hbConf srcHSL = 
    unsafePerformIO $ do 
     (_, s, log) <- runRWST srcHSL hbConf initHLang 
     return $ buildHSL hbConf s 

我实现的功能HSL HLangJS -> HLangJS如下图所示:

ujs :: HSL HLangJS -> HLangJS 
ujs srcHSL = 
    unsafePerformIO $ do 
     (a, s, log) <- runRWST srcHSL defaultHBConfig HLangJS 
     return a 

一切工作。但!!!我相信这不是最好的解决方案! 的配置和日志必须从变压器被要求在此代码所示:

ujs :: HSL a -> a 
ujs rws = 
    unsafePerformIO $ liftIO $ do 
     c <- ask 
     s <- get 
     (a, _, _) <- runRWST rws c s 
     return a 

但是这个代码不工作!我怎样才能实现这个?

+0

在过去'ujs'你想运行一个RWST动作,而与“配置”和初始状态提供它。您正在尝试执行'ask'和'get' - 这意味着您正在生成一个RWST块 - 但是然后在同一个动作中运行一个RWST块。 – Michael

+1

请勿使用'unsafePerformIO'。这是不安全的。 –

回答

2

首先,我认为你的HSL类型可能会更好。 HSL是monad,但您已将其限制。状态类型和monad“值”类型可能不同。任何时候,你都可以限制它们。

type HSL l a = RWST HBConfig [HBLog] l IO a 

或更好:

type HSL l = RWST HBConfig [HBLog] l IO 

其次,你的单子HSL可以转化HSL l a -> l只与配置和初始状态的默认值。如果你想隐藏这个参数,你应该考虑在哪里可以得到它们?例如,你可以从IO得到它:

ujs :: HSL l a -> IO l 
ujs act = do 
    config <- ... 
    initState <- ... 
    fst <$> execRWST act config initState 
+0

感谢您的回答,但这是我的主要问题:我在哪里可以获得配置和状态?有几个想法。工作继续。 – QSpider

+0

为什么你不想明确地添加它们? – freestyle

+0

谢谢你的想法。我实现了函数'ujs :: HSL HLangJS HLangJS - > HBConfig - > HLangJS - > HLangJS'。我回顾了应用程序架构。现在将配置和状态传递给该函数。 – QSpider