2010-03-01 21 views
8

में एकाधिक तर्कों पर लागू किया गया है क्या हैस्केल के "मानचित्र" या एकाधिक तर्कों के समान कुछ उपयोग करने का कोई तरीका है?नक्शा Haskell

यानी एक भी बिंदु (एक टपल के रूप में परिभाषित) के बीच की दूरी और अन्य बिंदुओं की एक सूची प्राप्त करने के लिए:,

map distance (-3,-3) buildings 

जाहिर है, वह काम नहीं करता, क्योंकि यह करने के लिए "दूरी" मैप करने के लिए कोशिश करता है (-3, -3), जहां दूरी उम्मीद दो tuples:

let distance pointA pointB = sqrt ((frst pointB - frst pointA) * (frst pointB - frst pointA) + (scnd pointB - scnd pointA) * (scnd pointB - scnd pointA)) 

दूरी तर्कों के रूप दो अंक लेता है: एक है (-3, -3) इस उदाहरण में, और एक सूची "इमारतों से चयन किया जाता है "।

(-3, -3) सिर्फ एक उदाहरण है। यह एक चर होना होगा; इसे फ़ंक्शन में हार्डकोड नहीं किया जा सकता है।

हो सकता है कि यह एक छोटे से अधिक समझ कर देगा:

buildings = [(3,-2),(2,1),(5,3),(4,3),(4,-1)] 

firstDiff pointA pointB = subtract (fst pointA) (fst pointB) 

secondDiff pointA pointB = subtract (snd pointA) (snd pointB) 

distance pointA pointB = sqrt ((firstDiff pointA pointB) * (firstDiff pointA pointB) +  (secondDiff pointA pointB) * (secondDiff pointA pointB)) 

--- What I need to happen here is a list "score" to be created by taking all distances from a point in a list lPoints to a point in list buildings. 

उत्तर

10

आप चाहते हैं:

map (distance (-3, -3)) buildings 

जो है

map f buildings 
    where f = distance (-3, -3) 
+0

दूरी तर्कों के रूप दो अंक लेता है: एक है (-3, -3) इस उदाहरण में, और एक सूची "से चयन किया जाता है इमारतों "। (-3, -3) सिर्फ एक उदाहरण है। यह एक चर होना होगा; इसे फ़ंक्शन में हार्डकोड नहीं किया जा सकता है। –

+2

स्पष्ट रूप से "नक्शा (दूरी पहली बिंदु) इमारतों" काम करेगा, है ना? या इसे स्पष्ट रूप से रखने के लिए: "बिल्डिंग प्वाइंट इमारतों = मानचित्र (दूरी बिंदु) इमारतों" – ondra

+0

बेशक आप एक चर के साथ (-3, -3) प्रतिस्थापित कर सकते हैं। – helium

19
allDistances src dests = map (\point -> distance src point) dests 

allDistances src dests = map (distance src) dests 

allDistances src = map (distance src) 

allDistances = map . distance 
+2

अच्छा कटौती फिक्सिंग को बंद कर रहा है यही कारण है कि प्वाइंट-फ्री फॉर्म –

2

ja की प्रतिक्रिया मैं पर टिप्पणी देखने के बाद मैं अनुमान लगा रहा हूं कि आपका उपयोग करना चाहते हैं

Prelude>:type zipWith 
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 

documentation कहता है:

zipWith, पहले तर्क के रूप में दिया समारोह के साथ ज़िप करने से जिप generalises एक tupling समारोह के बजाय। उदाहरण के लिए, संबंधित रकम की सूची तैयार करने के लिए ज़िप सूची (+) दो सूचियों पर लागू होती है।

तो यह ऊपर अपने कोड दिखाई दे सकता है की तरह:

Prelude> let dist a b = sqrt ((fst b - fst a) * (fst b - fst a) + (snd b - snd a) * (snd b - snd a)) 
Prelude> let buildings = [(1.0,1.0), (3.0,3.0), (4.0,4.0)] 
Prelude> let points = [ (1.2, 2.23), (2.23, 34.23), (324.3, 34.3) ] 
Prelude> zipWith dist points buildings 
[1.2461540835707277,31.239491032985793,321.7299799521332] 
0
distance (x, y) (z, w) = sqrt $ (x - z)^2 + (y - w)^2 

func1 = map . distance 

func2 starts ends = starts >>= flip func1 ends 

func1, समारोह आप वर्णित है, जबकि func2 समान है, लेकिन सिर्फ एक कई शुरुआत अंक के बजाय में ले जाता है और पाता है अंत बिंदुओं के साथ हर संयोजन के बीच दूरी।

0

दूरी सूत्र स्पष्ट है:

distance :: Floating a => (a,a) -> (a,a) -> a 
distance (x1,y1) (x2,y2) = sqrt $ (x2 - x1)^2 + (y2 - y1)^2 

नोट fst और snd साथ कोड कचरा बजाय तर्क विघटित मिलान पैटर्न का उपयोग।

किसी सूची में सभी बिंदुओं के लिए एक भी बिंदु से संबंधित दूरी इस partial application रूप हास्केल की भाषा में जाना जाता है तो

distanceFrom :: Floating a => (a,a) -> [(a,a)] -> [a] 
distanceFrom p = map (distance p) 

है, हालांकि तर्क लापता हो दिखाई देते हैं।distanceFrom में, हम उनमें से दो हैं:

  1. distance p जिसका मूल्य से p
  2. map (distance p) उस बिंदु की दूरी है अंक जिसका मूल्य की एक सूची की एक समारोह है उन बिंदुओं 'संबंधित दूरी है एक बिंदु की एक समारोह है p

छोटे कार्यों में छोटे कार्यों को गठबंधन करना आसान बनाने के लिए आंशिक अनुप्रयोग के लिए अपने हास्केल कार्यों को डिज़ाइन करने का प्रयास करें। जैसा कि ephemient's answer में उल्लेख किया गया है, आप इसे pointfree परिभाषा (कोई स्पष्ट तर्क नहीं) प्राप्त करने के लिए एक कदम आगे ले जा सकते हैं - एक और अधिक सुरुचिपूर्ण, उन्नत शैली।

lPoints में सभी बिंदुओं से buildings में प्रत्येक बिंदु के लिए दूरी,

main :: IO() 
main = do 
    mapM_ (putStrLn . unwords . map (printf "%6.3f")) score 
    where 
    score = [ distanceFrom x buildings | x <- lPoints ] 

उदाहरण के लिए तो है lPoints और buildings बराबर रही है, उत्पादन

 0.000 3.162 5.385 5.099 1.414 
3.162 0.000 3.606 2.828 2.828 
5.385 3.606 0.000 1.000 4.123 
5.099 2.828 1.000 0.000 4.000 
1.414 2.828 4.123 4.000 0.000

है लेकिन उस में एक छोटे से उबाऊ है इस विशेष मामले में सभी अनावश्यकता दी गई। बजाय strict upper triangle मुद्रित करने के लिए उपयोग करें

strictUpperTriangle :: [[a]] -> [[a]] 
strictUpperTriangle [] = [] 
strictUpperTriangle xs = go (init xs) 
    where go (x:xs) = tail x : map tail (go xs) 
     go [] = [] 

printSUT :: PrintfArg a => [[a]] -> IO() 
printSUT sut = putStr (unlines $ map pad sut) 
    where n = length sut 
     pad xs = let k = n - length xs in 
       unwords $ take k blanks ++ map (printf "%*.3f" w) xs 
     blanks = repeat (take w $ repeat ' ') 
     w = 6 :: Int 

main :: IO() 
main = printSUT tri 
    where 
    score = [ distanceFrom x buildings | x <- lPoints ] 
    tri = strictUpperTriangle score 

आउटपुट:

 3.162 5.385 5.099 1.414 
     3.606 2.828 2.828 
       1.000 4.123 
         4.000
+0

मुझे यह नहीं मिला। प्रिंटिंग चीजों की तरह क्या बात है? एलपी पॉइंट्स और बिल्डिंग बराबर होने पर यह केवल अनावश्यक है। –

+0

@trinithis "इस मामले में" जो मेरे सिर में नहीं था इसे मेरे उत्तर में बनाओ। धन्यवाद और संपादित! –