2016-12-26 70 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