7

में वापसी मान का उपयोग करना है, तो मैं अगले if condition को अगले if condition को निष्पादित करने के लिए या नहीं निर्धारित करने के लिए पिछले if condition की स्थिति की जांच करना चाहता हूं। प्रत्येक if condition एक मूल्य वापस कर सकता है।नेस्केड को सरल कैसे करें- यदि Haskell

संपादित करें: के लिए खेद है कि उदाहरण मैं पहले थोड़ा अजीब लग रही है ... :( यह मेरा वास्तविक उदाहरण है, और मैं if-then-elseके लिए goingToMove को आसान बनाने में करना चाहते हैं प्रदान की

goingToMove p routes points w h = 
         if canMove p points 
          -- the point can be moved in the map 
          then let r = routes ++ [p] 
            l = remainList p points 
           in move p r l w h 
          -- the point cannot be moved in the maps 
          else [] 

move p routes points w h = 
      if (length routes) == 2 
       then routes 
       else let one = goingToMove (tallRightCorner p) routes points w h in 
        if (null one) 
         then let two = goingToMove(tallRightBCorner p) routes points w h in 
          if (null two) 
           then let three = goingToMove (tallLeftBCorner p) routes points w h in 
            if (null three) 
             then .... 
             ...... -- until, let eight = .. 
             else three 
           else two 
         else one 

संपादित करें: बुरा उदाहरण जब इस बात जावा में लिखा है, मैं एक अस्थायी बूलियन ध्वज का उपयोग कर सकते हैं, और एक परिवर्तनशील डेटा वापस।

public String move (int number){ 
     // base case 
     if (number == 0){ 
      return "Finished the recursion"; 
     } 
     // general case 
     else { 
      String result; 
      boolean isNull = false; 

      if ((result = move(3)) == null){ 
       isNull = true; 
      } 
      else { 
       return result; 
      } 

      // continue to execute the if-conditions if the previous condition failed 
      if (isNull){ 
       if((result = move(2)) == null){ 
        isNull = true; 
       } 
       else { 
        return result; 
       } 
      } 

      if (isNull){ 
       if((result = move(1)) == null){ 
        isNull = true; 
       } 
       else { 
        return result; 
       } 
      } 

      return null; 
     } 
    } 

लेकिन हास्केल में, कोई म्यूटेबल डेटा नहीं है, और केवल if-then-else स्थिति है। तो कोड इच्छा इस तरह दिखता है, और मैं क्योंकि मेरा असली काम में इस सरल करने के लिए चाहते हैं, तो if-then-else के 8 स्तर जो भयानक और गंदा लग ....

move 0 = "Finished the recursion" 
move n = 
    let one = move 3 in 
    if null one 
     then let two = move 2 in 
      if null two 
       then let three = move 1 in 
         then null 
         else three 
       else two 
     else one 
+0

क्या 'चाल' आप अपने जावा कोड में कॉल कर रहे हैं जैसा कि आप 'चाल' परिभाषित कर रहे हैं? यदि ऐसा है, तो मैं नहीं देखता कि यह गैर-शून्य इनपुट के लिए असीमित रूप से कैसे लूप नहीं करता है। 'चाल (3) 'कॉल' चाल (3) 'कॉल' चाल (3)' – rampion

+0

आपके द्वारा प्रदान किया गया हैकेल कोड गलत प्रकार भी है। आप जावा कोड में किसी बिंदु पर स्पष्ट रूप से 'शून्य' लौट रहे हैं, जिसका अर्थ है कि हैकेल कोड 'Int -> शायद स्ट्रिंग' होना चाहिए, भले ही यह अनंत लूप न हो। ओह, और आपके द्वारा सुझाए गए हैंकेल कोड में सिंटैक्स त्रुटि भी है (इसमें एक लाइन के साथ एक लाइन गुम है?) जिससे आप यह पता लगाना मुश्किल हो जाते हैं कि आप क्या कर रहे हैं। – Carl

+0

मैंने एक वास्तविक उदाहरण दिया है :(क्षमा करें – code4j

उत्तर

16

जावा में अगर मैं निम्न कार्य करना चाहता था func1(args), func2(args), func3(args), func4(args) से पहला परिणाम जो गैर-शून्य देता है।

हास्केल में, मैं func1, func2, func3, और func4 मॉडल था कार्यों कि एक Maybe a मान दिया है, ताकि वे Nothing लौट सकते हैं अगर वे असफल रहे।

Nothing <|> x = x 
x  <|> _ = x 

तो मैं

func1 arg <|> func2 arg <|> func3 arg <|> func4 arg 

और जावा ऊपर परिवर्तित कर सकते हैं:

func1, func2, func3, func4 :: Int -> Maybe Result 

तो मैं (Control.Applicative से) <|> ऑपरेटर, जो Maybe a के लिए निम्नलिखित परिभाषा है उपयोग कर सकते हैं आलसी मूल्यांकन के चमत्कार के कारण, func2 arg का मूल्यांकन केवल तभी किया जाता है जब func1 argलौटाता है, जावा उदाहरण के समान।

+0

यह अच्छा लग रहा है, क्या इसका मतलब शून्य नहीं है? – code4j

+0

'हो सकता है' एक डेटा प्रकार है जिसमें दो रचनाकार हैं: 'कुछ भी नहीं :: शायद एक' और 'बस :: ए -> शायद ए'। इसे' डेटा 'के रूप में परिभाषित किया जा सकता है शायद एक = कुछ भी नहीं | बस एक ' – rampion

+0

सुंदर। Mmmmmm – AndrewC

1

संपादित हैं: यहाँ कुछ कोड है नए उदाहरण के लिए:

move p routes points w h 
    | length routes == 2 = routes 
    | otherwise = find (not . null) . map gtm [tallRightCorner, tallRightBCorner, tallLeftBCorner] 
    where gtm f = goingToMove (f p) routes points w h 

ध्यान दें कि यह संभवतः एक रिटर्न देता है। आप डिफ़ॉल्ट मामले में चिपकने के लिए fromMaybe का उपयोग कर सकते हैं।

result = func1(arg); 
if (result == null){ 
    result = func2(arg); 
    if (result == null){ 
    result = func3(arg); 
    if (result == null){ 
     result = func4(arg); 
    } 
    } 
} 
return result; 

क्या मैं अनिवार्य रूप से कर रहा हूँ खोजने है:

यहाँ पहले प्रस्तावित उदाहरण से पुराने (लेकिन typechecking) कोड

move 0 = "Finished the recursion" 
move n = concat . maybeToList . msum $ map move' [3,2,1] 
    where move' x = let mx = move x in if null mx then Nothing else Just mx 
+2

यह संकलित नहीं करता है (हालांकि प्रश्न में कोड संकलित नहीं करता है, इसलिए ...) –

+0

जो मुझे अपने मानसिक टाइपशेकर पर भरोसा करने के लिए मिलता है। – sclv

+0

मैंने एक वास्तविक उदाहरण दिया है :(क्षमा करें – code4j

12

अलावा <|> का अच्छा रोजगार कि rampion दिया और sclv के समान सुझाव से, एक और आम तरीका गार्ड उपयोग करने के लिए, और आलस्य का फायदा उठाने,

move :: Int -> Maybe String 
move n 
    | n == 0  = Just "Finished the recursion" 
    | isJust move3 = move3 
    | isJust move2 = move2 
    | isJust move1 = move1 
    | otherwise = Nothing 
     where 
     move3 = move 3 
     move2 = move 2 
     move1 = move 1 

आलस्य के कारण, move i (i = 3, 2, 1) ही है यदि आवश्यक हो तो मूल्यांकन किया गया।

दिया मामले में, move 3 <|> move 2 <|> move 1 बहुत अच्छे है, लेकिन ऐसे मामलों में जहां की स्थिति अलग वापसी प्रकार के साथ विभिन्न कार्यों का मूल्यांकन करने की आवश्यकता होती है, एक where खंड में गार्ड और आलसी बाइंडिंग का उपयोग अजीब नेस्टेड if से बचने के लिए प्राकृतिक समाधान हो सकता है रों।

+0

'जस्ट' और' बस 'का अर्थ क्या है ????? – code4j

+1

'जस्ट'' शायद एक 'का मूल्य निर्माता है। चूंकि आप वापस लौटते हैं और अपने जावा में 'नल' की जांच करते हैं, इसलिए हास्केल संस्करण 'हो सकता है' हो सकता है 'हो सकता है स्ट्रिंग' उचित समानता है। 'isJust' (' Data.Maybe' मॉड्यूल से उपलब्ध) परीक्षण करता है कि 'हो सकता है' मान 'बस एक' या 'कुछ भी नहीं' है, इसलिए 'बस move3'' के अनुरूप है (अगर परिणाम = चाल (3))! = शून्य) '[अगर आपका/तो है 'flipping। –

1

आप routes चाहते हैं, तो उसकी लंबाई 2 या goingToMove के अनुप्रयोगों है कि जो कोने समारोह p लिए आवेदन किया है के हिसाब से बदलती की एक श्रृंखला से पहले गैर-शून्य परिणाम है।

move p routes points w h 
    | length routes == 2 = routes 
    | otherwise = head 
       $ filter (not . null) 
       $ map tryMove corners 
    where tryMove f = goingToMove (f p) routes points w h 
      corners = [ tallRightCorner 
        , tallRightBCorner 
        , tallLeftBCorner 
        -- et cetera 
        ] 
0

हो सकता है कि (नीचे उदाहरण में, आप झंडा एक करने के लिए सेट के साथ समारोह कहेंगे) प्रत्यावर्तन के लिए एक फ्लैग जोड़ने के बिना हो सकता है एक विकल्प: 1

कदम पी मार्गों अंक

move p routes points w h flag 
    | (length routes) == 2 = routes 
    | otherwise = 
     if null result then move p routes points w h (flag+1) 
     else result 
     where result = case flag of 
         1 -> goingToMove (tallRightCorner p) routes points w h 
         2 -> goingToMove (tallRightBCorner p) routes points w h 
         3 -> goingToMove (tallLeftBCorner p) routes points w h 
         --...etc. 
         _ -> []