2012-02-05 6 views
5

दूसरे दिन मैंने एक मैट्रिक्स में संख्याओं का एक समूह एकत्र करने के लिए एक छोटा प्रोग्राम लिखा - data Matrix = Matrix [[Int]] कोने पर शुरू - Corner और पथ - [Direction] सभी का पालन करें तो LeftUp करने और Rightहैस्केल में पॉलिमॉर्फिज्म - इसे अलग-अलग नाम दिए बिना एक फ़ंक्शन के कई संस्करणों का उपयोग करके

turnLUR :: Transformable a => (Corner, Direction) -> a -> a 

मैं इस समारोह का उपयोग करें - तीन प्रकार के एक वर्ग Transformable

तो मैं एक समारोह है कि एक परिवर्तन समारोह उत्पन्न करता है, कि किसी दिए गए कोने और दिशा बदल जाता है के उदाहरण हैं "फसल" मैट्रिक्स में सभी नंबरों को:

harvest :: Matrix → [(Corner,Direction)] → [Int] 
harvest _ [] = [] 
harvest (Matrix []) _ = [] 
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction) 
        where f1 = turnLUR cd -- Matrix -> Matrix 
          f2 = turnLUR cd -- Corner -> Corner 
          f3 = turnLUR cd -- Direction -> Direction 
          Matrix (b:bs) = f1 as -- b = first line of [[Int]] 
          fcfd (c,d) = (f2 c,f3 d) 
          csds' = map fcfd csds 

अब मेरे सवाल का कारण है कि मैं f1, f2 और f3 बजाय एक समारोह का उपयोग करने का लिख ​​है f तीन बार (! मेरे मन में सूखा रखने) - सभी तीन प्रकार Corners, Directions और Matrixclass Transformable के उदाहरण हैं। "एक ही" समारोह के तीन संस्करण बनाने -

मैं कैसे बिना कि कोड लिखने होगा?

उत्तर

11

यह monomorphism restriction की वजह से है। यह एक स्पष्ट प्रकार हस्ताक्षर दो, और आप एक ही समारोह हर बार पुन: उपयोग करने में सक्षम हो जाएगा:

harvest :: Matrix → [(Corner,Direction)] → [Int] 
harvest _ [] = [] 
harvest (Matrix []) _ = [] 
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction) 
        where f :: Transformable a => a -> a 
          f = turnLUR cd 
          Matrix (b:bs) = f as -- b = first line of [[Int]] 
          fcfd (c,d) = (f c,f d) 
          csds' = map fcfd csds 

वैकल्पिक रूप से, आप इसे अपनी फ़ाइल के शीर्ष पर {-# LANGUAGE NoMonomorphismRestriction #-} डालकर बंद कर सकते हैं।

मोनोमोर्फिज्म प्रतिबंध अच्छी तरह से पसंद नहीं है - यहां तक ​​कि जीएचसी का मैनुअल इसे dreaded monomorphism restriction के रूप में संदर्भित करता है - लेकिन कुछ मुश्किल कोने के मामले हैं, विशेष रूप से साझा करने से संबंधित (विकी पेज जो मैं अधिक जानकारी के लिए जुड़ा हुआ हूं) देखें, कि यह बचा जाता है। इस मामले में, मैं सिर्फ प्रकार हस्ताक्षर जोड़ने की सिफारिश करता हूं।

+3

ध्यान दें कि monomorphism प्रतिबंध केवल, व्यर्थ शैली में लिखा कार्यों (और साथ ही मानों कार्यों नहीं हैं) को प्रभावित करता है, इसलिए यदि आप को परिभाषित 'f' स्पष्ट मानकों का प्रयोग करके, यह प्रतिबंध से प्रभावित नहीं होगा, भले ही आप इसे एक प्रकार का हस्ताक्षर न दें। – sepp2k

+0

तो प्रकार हस्ताक्षर 'f :: ट्रांसफॉर्मेबल ए => ए -> ए 'फ़ंक्शन को किसी प्रकार के हस्ताक्षर पर निर्दिष्ट किया गया है; और इसके बिना संकलक 'f' को 'मैट्रिक्स -> मैट्रिक्स' प्रकार के रूप में घटा देता है क्योंकि यह इसका पहला उपयोग है। इसे स्पष्ट करने के लिए बहुत बहुत धन्यवाद। विशेष रूप से मुझे नहीं पता था कि हस्ताक्षर इस monomorphism प्रतिबंध को हल कर सकता है। – epsilonhalbe

संबंधित मुद्दे