سؤال

أنا أحاول أن أفهم ما المشغل نقطة في هذا هاسكل كود:

sumEuler = sum . (map euler) . mkList

كامل شفرة المصدر أدناه.

فهمي

المشغل نقطة يأخذ وظيفتين sum ونتيجة map euler ونتيجة mkList كما الإدخال.

ولكن ، sum ليست وظيفة بل هو حجة من وظيفة ، أليس كذلك ؟ ماذا يجري هنا ؟

أيضا, ما هو (map euler) تفعل ؟

رمز

mkList :: Int -> [Int]
mkList n = [1..n-1]

euler :: Int -> Int
euler n = length (filter (relprime n) (mkList n))

sumEuler :: Int -> Int
sumEuler = sum . (map euler) . mkList
هل كانت مفيدة؟

المحلول

وببساطة، . هو تكوين وظيفة، مثلما هو الحال في الرياضيات:

f (g x) = (f . g) x

في قضيتك، كنت تقوم بإنشاء وظيفة جديدة، sumEuler التي يمكن أيضا أن يعرف مثل هذا:

sumEuler x = sum (map euler (mkList x))

ويسمى النمط في المثال الخاص بك "خالية من نقطة" على غرار - يتم حذف الحجج على وظيفة. وهذا يجعل لرمز أكثر وضوحا في كثير من الحالات. (ويمكن أن يكون من الصعب جروك في المرة الأولى التي نرى ذلك، ولكن سوف تعتاد على ذلك بعد فترة من الوقت، وهي لغة هاسكل المشترك.)

إذا كنت لا تزال مشوشة، فإنه قد تساعد على ربط . إلى ما يشبه الأنابيب UNIX. إذا يصبح الناتج f في إدخال g، والذي يصبح مدخلات h في الانتاج، وكنت كتبت ذلك على سطر الأوامر مثل f < x | g | h. في هاسكل، . يعمل مثل | UNIX، ولكن "إلى الوراء" - h . g . f $ x. أجد هذه الرموز أن تكون مفيدة جدا عندما، مثلا، وتجهيز قائمة. بدلا من بعض البناء غير عملي مثل map (\x -> x * 2 + 10) [1..10]، هل يمكن أن مجرد كتابة (+10) . (*2) <$> [1..10]. (وإذا كنت تريد تطبيق فقط تلك الوظيفة إلى قيمة واحدة؛.! انها (+10) . (*2) $ 10 اتساقا)

وويكي هاسكل لديه مادة جيدة مع بعض مزيد من التفاصيل: http://www.haskell.org/ haskellwiki / Pointfree

نصائح أخرى

على .مشغل يؤلف وظائف.على سبيل المثال ،

a . b

حيث a و ب هي وظائف جديدة وظيفة الذي يعمل ب على الحجج ، ثم على تلك النتائج.التعليمات البرمجية الخاصة بك

sumEuler = sum . (map euler) . mkList

هو بالضبط نفس:

sumEuler myArgument = sum (map euler (mkList myArgument))

ولكن نأمل أن أسهل في القراءة.السبب هناك parens حول خريطة يولر لأنه يجعل أوضح أن هناك 3 مهام كونها تتألف: مجموع, خريطة يولر و mkList - خريطة يولر هو وظيفة واحدة.

وsum هي وظيفة في مقدمة حزقيل، وليس حجة لsumEuler. أنه يحتوي على نوع

Num a => [a] -> a

والمشغل . تكوين وظيفة لديها اكتب

(b -> c) -> (a -> b) -> a -> c

وهكذا لدينا

sum                        :: Num a => [a] -> a
map                        :: (a -> b) -> [a] -> [b]
euler                      :: Int -> Int
mkList                     :: Int -> [Int]
(map euler)                :: [Int] -> [Int]
(map euler) . mkList       :: Int -> [Int]
sum . (map euler) . mkList :: Int -> Int

لاحظ أن Int هو مثيل Num.

وو. يستخدم المشغل لتكوين وظيفة. تماما مثل الرياضيات، وإذا كان لديك وظائف و (خ) و (ز) (س) و. ز يصبح و (ز (خ)).

والخريطة هي وظيفة المدمج الذي ينطبق على وظيفة إلى قائمة. من خلال وضع وظيفة بين قوسين يتم التعامل مع وظيفة كحجة. مصطلح لهذا هو الضمادة . يجب أن ننظر إلى أن ما يصل.

ما هو يفعله هو ان الامر يستغرق وظيفة مع القول حجتين، فإنه ينطبق يولر حجة. (خريطة يولر) أليس كذلك؟ والنتيجة هي وظيفة جديدة، والتي تأخذ وسيطة واحدة فقط.

والمبلغ. (خريطة يولر). mkList هو في الأساس وسيلة يتوهم من وضع كل ذلك معا. يجب أن أقول، يا حزقيل غير صدئ قليلا ولكن ربما يمكنك وضع تلك الوظيفة مشاركة معا نفسك؟

المشغل نقطة ينطبق الدالة على اليسار (sum) إلى إخراج الدالة على الحق.في حالتك أنت تسلسل عدة وظائف معا - كنت تمر نتيجة mkList إلى (map euler), ثم يمر نتيجة ذلك sum. هذا الموقع وقد مقدمة جيدة إلى العديد من المفاهيم.

<اقتباس فقرة>   

دوت مشغل في هاسكل

     

وأنا أحاول أن أفهم ما يقوم به المشغل نقطة في هذا الرمز هاسكل:

sumEuler = sum . (map euler) . mkList

الجواب باختصار

ورمز المكافئة بدون نقاط، وهذا هو فقط

sumEuler = \x -> sum ((map euler) (mkList x))

وأو بدون لامدا

sumEuler x = sum ((map euler) (mkList x))

ولأن نقطة (.) إلى تكوين وظيفة.

أطول الجواب

أولا، دعونا تبسيط تطبيق جزئي للeuler إلى map:

map_euler = map euler
sumEuler = sum . map_euler . mkList

والآن لدينا فقط النقاط. ما دلت عليه هذه النقاط؟

من <لأ href = "http://hackage.haskell.org/package/base-4.10.1.0/docs/src/GHC.Base.html#". يختلط = "نوفولو noreferrer"> المصدر :

<اقتباس فقرة>
(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

وهكذا (.) هو يؤلف مشغل .

يؤلف

في الرياضيات، ونحن قد كتابة تكوين وظائف، و (خ) و (ز) (س)، وهذا هو، و (ز (خ))، و

<اقتباس فقرة>   

و(و ∘ ز) (س)

والتي يمكن قراءتها "و يتآلف مع ز".

وحتى في هاسكل، و ∘ ز، أو F يتآلف مع غرام، يمكن كتابة:

f . g

والتكوين هو النقابي، وهو ما يعني أن f (ز (ح (خ)))، وكتب مع المشغل التكوين، يمكن أن تترك خارج الأقواس دون أي غموض.

وهذا هو، منذ (و ∘ ز) ∘ ساعة ما يعادل F ∘ (ز ∘ ح)، يمكننا ببساطة كتابة و ∘ ز ∘ ساعة.

الدوران إلى الخلف

وتحلق إلى تبسيط لدينا في وقت سابق، وهذا:

sumEuler = sum . map_euler . mkList

وفقط يعني أن sumEuler هو تكوين غير مطبقة تلك الوظائف:

sumEuler = \x -> sum (map_euler (mkList x))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top