मैं वर्तमान में एक प्रोग्रामिंग भाषा के लिए एक साधारण दुभाषिया पर काम कर रहा हूं और मेरे पास एक डेटा प्रकार है:
data Expr
= Variable String
| Number Int
| Add [Expr]
| Sub Expr Expr
और मेरे पास कई कार्य हैं जो सरल काम करते हैं जैसे:
-- Substitute a value for a variable
substituteName :: String -> Int -> Expr -> Expr
substituteName name newValue = go
where
go (Variable x)
| x == name = Number newValue
go (Add xs) =
Add $ map go xs
go (Sub x y) =
Sub (go x) (go y)
go other = other
-- Replace subtraction with a constant with addition by a negative number
replaceSubWithAdd :: Expr -> Expr
replaceSubWithAdd = go
where
go (Sub x (Number y)) =
Add [go x, Number (-y)]
go (Add xs) =
Add $ map go xs
go (Sub x y) =
Sub (go x) (go y)
go other = other
लेकिन इन कार्यों में से प्रत्येक में, मुझे उस हिस्से को दोहराना होगा जो फ़ंक्शन के एक हिस्से में केवल एक छोटे से बदलाव के साथ कोड को पुनरावर्ती कहता है। क्या इसे और अधिक उदारता से करने का कोई मौजूदा तरीका है? मुझे इस भाग को कॉपी और पेस्ट नहीं करना होगा:
go (Add xs) =
Add $ map go xs
go (Sub x y) =
Sub (go x) (go y)
go other = other
और हर बार एक ही मामले को बदल दें क्योंकि यह इस तरह से डुप्लिकेट कोड के लिए अक्षम है।
एकमात्र समाधान मैं साथ आ सकता है एक फ़ंक्शन है जो पूरे डेटा संरचना पर पहले एक फ़ंक्शन को कॉल करता है और फिर इसके परिणाम पर पुनरावर्ती रूप से होता है:
recurseAfter :: (Expr -> Expr) -> Expr -> Expr
recurseAfter f x =
case f x of
Add xs ->
Add $ map (recurseAfter f) xs
Sub x y ->
Sub (recurseAfter f x) (recurseAfter f y)
other -> other
substituteName :: String -> Int -> Expr -> Expr
substituteName name newValue =
recurseAfter $ \case
Variable x
| x == name -> Number newValue
other -> other
replaceSubWithAdd :: Expr -> Expr
replaceSubWithAdd =
recurseAfter $ \case
Sub x (Number y) ->
Add [x, Number (-y)]
other -> other
लेकिन मुझे लगता है कि पहले से ही ऐसा करने का एक सरल तरीका होना चाहिए। क्या मैं कुछ भूल रहा हूँ?
Add :: Expr -> Expr -> Expr
इसके बजाय परिभाषित करें Add :: [Expr] -> Expr
, और Sub
पूरी तरह से छुटकारा पाएं ।
recurseAfter
है ana
भेस में। आप एनामर्फिम्स को देखना चाहते हैं और कर सकते हैं recursion-schemes
। कहा जा रहा है, मुझे लगता है कि आपका अंतिम समाधान उतना ही छोटा है जितना कि यह हो सकता है। आधिकारिक recursion-schemes
एनामॉर्फिज्म पर स्विच करने से बहुत बचत नहीं होगी।