2011-06-06 18 views
13

मैंने अभी हास्केल सीखना शुरू कर दिया। मुझे लगता है कि मुझे मूल बातें मिल गई हैं, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि मैं वास्तव में खुद को कार्यात्मक रूप से सोचने के लिए मजबूर कर रहा हूं।गणनाओं पर कार्यों का निर्माण

data Dir = Right | Left | Front | Back | Up | Down deriving (Show, Eq, Enum) 
inv Right = Left 
inv Front = Back 
inv Up = Down 

वैसे भी, मैं क्या कर रहा हूँ के jist प्रत्येक "डिर" और इसके विपरीत/निवेश संबंधी निर्णय निर्माताओं के बीच मैप करने के लिए एक समारोह बनाने के लिए है। मुझे पता है कि मैं इसे आसानी से एक और 3 लाइनों के लिए जारी रख सकता हूं, लेकिन मैं मदद नहीं कर सकता लेकिन आश्चर्यचकित हूं कि कोई बेहतर तरीका है या नहीं। मैंने जोड़ने की कोशिश की:

inv a = b where inv b = a 

लेकिन स्पष्ट रूप से आप ऐसा नहीं कर सकते हैं। तो मेरा सवाल यह है: क्या इस कार्य को बनाने के लिए शेष इनवर्ड्स या पूरी तरह से बेहतर तरीका उत्पन्न करने का कोई तरीका है?

बहुत धन्यवाद।

उत्तर

18

यदि Up और Down और अन्य के बीच जोड़ी एक महत्वपूर्ण विशेषता है तो हो सकता है कि यह ज्ञान प्रकार में दिखाई दे।

data Axis = UpDown | LeftRight | FrontBack 
data Sign = Positive | Negative 
data Dir = Dir Axis Sign 

inv अब आसान है।

+0

यही बेहतर है। प्रकारों में मूल अवधारणा (आयाम और दिशा) को सटीक रूप से कैप्चर करें। –

+0

समझ में आता है। "साइन" पर "आविष्कार सकारात्मक" के विपरीत खोजना "Dir" पर "आक्रमण दाएं" के विपरीत खोजने से बेहतर है। तो एक 'उलटा' साफ करने का एकमात्र तरीका यह है कि आप वास्तव में छोटे बदलाव कर रहे हैं ... – rcbuchanan

+1

@ आरसीबी 451, आप बिंदु खो रहे हैं। तथ्य यह है कि 'साइन' में कम डेटा कन्स्ट्रक्टर आकस्मिक है (हालांकि निश्चित रूप से फायदेमंद)। मुख्य अवलोकन यह है कि 'वाम' और 'दाएं' के बीच घनिष्ठ संबंध उनके प्रकारों में दिखाई दे सकते हैं, इसी प्रकार दूरदराज के संबंध (उदाहरण के लिए) 'बाएं' और 'शीर्ष' के बीच। प्रकार प्रणाली इनवेरिएंट्स में मदद करने के लिए है: अधिक प्रकार के साथ आप अधिक सटीक आविष्कार व्यक्त कर सकते हैं। – Lambdageek

2

क्या आपके पास इस फ़ंक्शन से संबंधित सूचकांक पर एक बंद-फ़ॉर्म समाधान है? यदि हां, तो आप चीजों को सरल बनाने के लिए Enum का उपयोग कर सकते हैं। उदाहरण के लिए,

import Prelude hiding (Either(..)) 

data Dir = Right 
     | Front 
     | Up 

     | Left 
     | Back 
     | Down 
    deriving (Show, Eq, Ord, Enum) 

inv :: Dir -> Dir 
inv x = toEnum ((3 + fromEnum x) `mod` 6) 

ध्यान दें, यह कंस्ट्रक्टर्स के आदेश पर निर्भर करता है!

*Main> inv Left 
Right 
*Main> inv Right 
Left 
*Main> inv Back 
Front 
*Main> inv Up 
Down 

यह बहुत सी की तरह है, निर्माताओं के आदेश कारनामे, और अन-Haskelly है। रचनात्मकता और उनके दर्पणों के बीच मैपिंग को परिभाषित करने के लिए अंकगणित के उपयोग से परहेज करने के लिए का एक समझौता का उपयोग करना है।

import Prelude hiding (Either(..)) 

data Dir = A NormalDir 
     | B MirrorDir 
    deriving Show 

data NormalDir = Right | Front | Up 
    deriving (Show, Eq, Ord, Enum) 

data MirrorDir = Left | Back | Down  
    deriving (Show, Eq, Ord, Enum) 

inv :: Dir -> Dir 
inv (A n) = B (toEnum (fromEnum n)) 
inv (B n) = A (toEnum (fromEnum n)) 

जैसे

*Main> inv (A Right) 
B Left 
*Main> inv (B Down) 
A Up 

तो कम से कम हमें अंकगणित करने की आवश्यकता नहीं थी। और प्रकार दर्पण के मामलों में अंतर करते हैं। हालांकि, यह बहुत ही हास्कली है। मामलों की गणना करना बिल्कुल सही है! दूसरों को किसी बिंदु पर अपना कोड पढ़ना होगा ...

2
pairs = ps ++ map swap ps where 
    ps = [(Right, Left), (Front, Back), (Up, Down)] 
    swap (a, b) = (b, a) 

inv a = fromJust $ lookup a pairs  

[संपादित करें]

या कैसे इस बारे में?

inv a = head $ delete a $ head $ dropWhile (a `notElem`) 
     [[Right,Left],[Front,Back],[Up,Down]] 
1

मुझे नहीं लगता कि मैं इस की सलाह देते हैं, लेकिन मेरे मन में सरल उत्तर में जोड़ने के लिए होगा:

inv x = fromJust $ find ((==x) . inv) [Right, Front, Up] 

मैं करने के लिए Landei के जवाब में सुधार करने का विरोध नहीं कर सकता मेरी शैली फिट यहाँ एक समान है और थोड़ा और अधिक सुझाए गए समाधान है कि अन्य परिभाषाओं की जरूरत नहीं है है:

inv a = fromJust $ do pair <- find (a `elem`) invList 
         find (/= a) pair 
    where invList = [[Right, Left], [Up, Down], [Front, Back]] 

यह हो सकता है कि इकाई का उपयोग करता है।

+0

एचएम? बग? यह 'inv x = inv x' कहने से बेहतर नहीं है। – comonad

+1

मेरा मतलब है कि परिभाषाओं के बाद इसे 'आवे राइट', 'इनव फ्रंट', 'इनव अप' के लिए पहले से लिखा गया है। [अपने लिए देखें कि यह काम करता है] (https://ideone.com/Uc9Px)। –

+0

आह, ठीक है। उन अतिरिक्त लाइनों के साथ, यह काम करता है। – comonad

1

यह जानना अच्छा है कि Enum eration शून्य से शुरू होता है।

स्मरक: fmap fromEnum [False,True] == [0,1]


import Data.Bits(xor) 

-- Enum:  0 1   2 3  4 5 
data Dir = Right | Left | Front | Back | Up | Down 
      deriving (Read,Show,Eq,Ord,Enum,Bounded) 

inv :: Dir -> Dir 
inv = toEnum . xor 1 . fromEnum 
संबंधित मुद्दे