हां, यह सीमित सीमा तक किया जा सकता है।
लेकिन पहले हम
{-# LANGUAGE Rank2Types #-}
तो मैं अच्छे शो समर्थन प्राप्त कर सकते हैं के
data M a b = M { name :: Int -> String -> String, eval :: a -> b }
मैं अपने नाम करने के लिए और अधिक संरचना जोड़ रहा परिभाषित करते हैं की आवश्यकता होगी। अब
class Magic m where
magic :: M a b -> m a b
instance Magic M where
magic = id
instance Magic (->) where
magic (M _ f) = f
, प्रकार पर विचार करें::
type MyFunc a b = forall m. Magic m => m a b
magic
का परिणाम प्रकार या तो (a -> b)
या एक M a b
है;)
फिर एक वर्ग को परिभाषित करने देता है।
तो इसका उपयोग MyFunc
के सदस्य के रूप में किया जा सकता है। अब, इस प्रकार कुछ हद तक नाकाफी है, क्योंकि आप उदाहरणों उस पर प्रेषण नहीं कर सकते हैं, लेकिन इसका मतलब यह है कि
inc :: MyFunc Int Int
inc = magic (M (const (showString "inc")) (+1))
test :: Int
test = inc 1
काम करता है ठीक।
हम उन्हें दिखाने का एक अच्छा तरीका भी बना सकते हैं। भले ही हम MyFunc
पर शो का उपयोग नहीं कर सकते हैं, हम इसे M
के लिए परिभाषित कर सकते हैं।
instance Show (M a b) where
showsPrec d (M s _) = s d
फिर हम एक समारोह हम M a b
(और विस्तार के किसी भी MyFunc
द्वारा) एक M a b
बाहर निकलने के लिए करने के लिए आवेदन कर सकते हैं कर सकते हैं।
m :: M a b -> M a b
m = id
और हम MyFunc
रों को दिखाने के लिए एक विशेष Combinator परिभाषित कर सकते हैं:
showM :: MyFunc a b -> String
showM f = show (m f)
फिर हम खेल सकते हैं। हम MyFunc
एस की रचनाओं को परिभाषित कर सकते हैं।
infixr 9 .#
(.#) :: MyFunc b c -> MyFunc a b -> MyFunc a c
f .# g = magic (M
(\d -> showParen (d > 9) $ showsPrec 10 (m f) .
showString " . " .
showsPrec 9 (m g))
(f . g))
inc2 :: MyFunc Int Int
inc2 = inc .# inc
test2 :: Int
test2 = inc2 1
bar, baz :: String
bar = showM inc
baz = showM inc2
और क्योंकि मैं नाम करने के लिए पर्याप्त संरचना दे दी है, हम और भी जटिल रचनाओं के लिए सही parenthesization, अनावश्यक कोष्ठकों के बिना मिलता है।
*Main> showM $ inc2 .# inc
"(inc . inc) . inc"
*Main> showM $ inc .# inc2
"inc . inc . inc"
लेकिन याद रखें, आप, MyFunc
के लिए किसी भी इंस्टेंस को परिभाषित करने में सक्षम नहीं होगा, क्योंकि यह केवल एक type
, और नहीं एक newtype
हो सकता है। उदाहरणों को परिभाषित करने के लिए आपको उन्हें M
पर परिभाषित करना होगा, और फिर उस प्रकार को बदलने के लिए m
का उपयोग करें ताकि अंतर्निहित प्रेषण को पकड़ने के लिए एक प्रकार हो।
रैंक 2 प्रकार की वजह से, यदि आप स्थानीय संदर्भों में इनका भारी उपयोग करते हैं, तो आप NoMonoLocalBinds
और/या NoMonomorphismRestriction
चालू करना भी चाह सकते हैं।
यह भयानक है। मुझे यह पसंद है। –