में एकाधिक राज्यों का संयोजन मैं एक प्रोग्राम लिख रहा हूं जो डेमॉन के रूप में चलता है। डेमॉन बनाने के लिए, उपयोगकर्ता के लिए आवश्यक वर्गों (उनमें से एक एक डेटाबेस है) इन कक्षाओं में है कार्यों प्रपत्र StateT s IO a
, की प्रकार हस्ताक्षर है, वे लेकिन s
के लिए अलग है में से प्रत्येक के लिए कार्यान्वयन का एक सेट की आपूर्ति प्रत्येक वर्ग।स्टेटटी
import Control.Monad (liftM)
import Control.Monad.State (StateT(..), get)
class Hammer h where
driveNail :: StateT h IO()
data ClawHammer = MkClawHammer Int -- the real implementation is more complex
instance Hammer ClawHammer where
driveNail = return() -- the real implementation is more complex
-- Plus additional classes for wrenches, screwdrivers, etc.
अब मैं एक रिकॉर्ड कार्यान्वयन प्रत्येक "स्लॉट" के लिए उपयोगकर्ता द्वारा चुना प्रतिनिधित्व करता है कि परिभाषित कर सकते हैं:
वर्गों में से प्रत्येक के इस पद्धति का अनुसरण करता मान लीजिए।
data MultiTool h = MultiTool {
hammer :: h
-- Plus additional fields for wrenches, screwdrivers, etc.
}
और डेमॉन StateT (MultiTool h ...) IO()
इकाई में अपना काम का सबसे करता है।
अब, क्योंकि multitool में एक हथौड़ा है, मैं इसे किसी भी स्थिति में उपयोग कर सकता हूं जहां एक हथौड़ा की आवश्यकता होती है। दूसरे शब्दों में, MultiTool
प्रकार कक्षाएं इसमें से किसी को लागू कर सकते हैं, अगर मैं इस तरह कोड लिखने:
stateMap :: Monad m => (s -> t) -> (t -> s) -> StateT s m a -> StateT t m a
stateMap f g (StateT h) = StateT $ liftM (fmap f) . h . g
withHammer :: StateT h IO() -> StateT (MultiTool h) IO()
withHammer runProgram = do
t <- get
stateMap (\h -> t {hammer=h}) hammer runProgram
instance Hammer h => Hammer (MultiTool h) where
driveNail = withHammer driveNail
लेकिन के कार्यान्वयन withHammer
, withWrench
, withScrewdriver
, आदि मूल रूप से समान हैं। यह कुछ इस तरह लिखने के लिए सक्षम होने के लिए अच्छा होगा ...
--withMember accessor runProgram = do
-- u <- get
-- stateMap (\h -> u {accessor=h}) accessor runProgram
-- instance Hammer h => Hammer (MultiTool h) where
-- driveNail = withMember hammer driveNail
लेकिन निश्चित है कि संकलन नहीं होगा की।
मुझे संदेह है कि मेरा समाधान बहुत ऑब्जेक्ट उन्मुख है। क्या कोई बेहतर तरीका है? मोनाड ट्रांसफार्मर, शायद? किसी भी सुझाव के लिए अग्रिम धन्यवाद।
संयोग से, मैं एक त्वरित संपादित अपने कोड है क्योंकि आपके सरलीकरण में 'ClawHammer' के कार्यान्वयन को छोड़ते हुए बनाया आपने ऐसा कुछ बनाया जो शायद आपके पास नहीं था। –