您可以確定有問題的模塊。也就是說,一個基礎模塊中定義的數據類型:
module Base where
data MyModule = MyModule {
doThis_ :: SomeStack(),
doThat_ :: SomeStack()
}
你需要每個模塊出口(的原因下劃線將很快變得明顯)的東西。
然後,你可以在每個模塊的定義值這個類型,例如:
module DryRun(moduleImpl) where
import Base
moduleImpl :: MyModule
moduleImpl = MyModule doThis doThat
-- doThis and doThat defined as above, with liftIO . putStrLn
module Do(moduleImpl) where
import Base
moduleImpl :: MyModule
moduleImpl = MyModule doThis doThat
-- doThis and doThat defined as above, where the real work gets done
我不使用記錄語法,以確保構建MyModule
值,如果MyModule
變化,類型檢查器在大多數情況下開始抱怨。
在客戶端模塊,你可以做
module Client where
import DryRun
-- import Do -- uncomment as needed
doThis = doThis_ moduleImpl
doThat = doThat_ moduleImpl
-- do whatever you want here
現在你知道,同樣的操作由兩個模塊輸出。這確實是單調乏味的,但是由於Haskell沒有一流的模塊,所以你總是需要解決模塊系統的限制。好處是您只需編寫一次Base和Client模塊,並且您可以開始定義在MyModule
值上運行的組合器。例如。
doNothing = MyModule (return()) (return())
addTracing impl = MyModule ((liftIO $ putStrLn "DoThis") >> doThis_ impl)
((liftIO $ putStrLn "DoThat") >> doThat_ impl)
將允許您通過addTracing doNothing
更換DryRun
模塊實現,如果我沒有記錯。
是否讓相同類型類型的兩個實現實例成爲選項? – 2012-04-28 12:06:09
@GregBacon那麼,monad棧的兩個副本肯定是一個選項,但如果有一些不涉及複製的東西,我會使用它。 – 2012-04-28 12:17:37
在兩個模塊上運行haddock並比較生成的文檔? – 2012-04-28 13:34:19