سؤال

وقبل فترة، سألت <لأ href = "https://stackoverflow.com/questions/395995/when-should-i-use-and-can-it-always-be-replaced-with-parentheses "> سؤال حول $، وحصلت على اجابات مفيدة - في الواقع، وأعتقد أنني فهمت كيفية استخدامه

.

ويبدو أنني كنت مخطئ: (

ويوضح هذا المثال حتى في البرنامج التعليمي:

instance Monad [] where
   xs >>= f = concat . map f $ xs

وأنا لا يمكن للحياة لي ترى لماذا كان يستخدم $ هناك. ghci لا يساعد لي سواء، وحتى الاختبارات أفعل هناك يبدو لاظهار التكافؤ مع الإصدار ببساطة تجاهل $. يمكن للشخص توضيح هذا بالنسبة لي؟

هل كانت مفيدة؟

المحلول

ويستخدم $ هنا لأنه لديه أسبقية أقل من الطلب وظيفة عادية. وهناك طريقة أخرى لكتابة هذا الرمز مثل ذلك:

instance Monad [] where
   xs >>= f = (concat . map f) xs

والفكرة هنا هي لبناء أول وظيفة (concat . map f) ومن ثم تطبيقه على حجتها (xs). كما هو مبين، ويمكن أيضا أن يتم ذلك ببساطة عن طريق وضع قوسين حول الجزء الأول.

لاحظ أن إهمال $ في التعريف الأصلي لم يكن ذلك ممكنا، وسوف يؤدي إلى خطأ نوع. وذلك لأن مشغل تكوين وظيفة (و.) له الأسبقية أقل من الطلب وظيفة عادية تحول بشكل فعال في التعبير:

instance Monad [] where
  xs >>= f = concat . (map f xs)

والذي لا معنى له، لأن الحجة الثانية للمشغل تكوين وظيفة ليست وظيفة على الإطلاق. على الرغم من أن التعريف التالي لا معنى له:

instance Monad [] where
  xs >>= f = concat (map f xs)

وبالمناسبة، هذا هو أيضا التعريف كنت تفضل، لأنه يبدو لي أن تكون أكثر وضوحا الكثير.

نصائح أخرى

وأود أن أشرح لماذا IMHO هذا ليس أسلوب المستخدمة هناك:

instance Monad [] where
  xs >>= f = concat (map f xs)

وconcat . map f مثال على ما يسمى الكتابة على غرار pointfree. حيث يعني pointfree "بدون نقطة التطبيق". تذكر أنه في الرياضيات، في y=f(x) التعبير، ونحن نقول أن يتم تطبيق f على x نقطة. في معظم الحالات، يمكنك القيام به في الواقع الخطوة الأخيرة، ليحل محل:

f x = something $ x

مع

f = something

ومثل f = concat . map f، وهذا هو في الواقع أسلوب pointfree. وهو أكثر وضوحا يمكن القول، ولكن الاسلوب pointfree يعطي وجهة نظر مختلفة والتي هي أيضا مفيدة، حتى في بعض الأحيان يتم استخدامها حتى عند عدم الحاجة إليها بالضبط.

وتحرير: لقد حل محل المجدي مع pointfree وإصلاح بعض الأمثلة، بعد تعليق بواسطة السدير الذي أود أن أشكر

والسبب يستخدم هنا $ هو ظبية إلى نوع توقيع (.):

(.) :: (b -> c) -> (a -> c) -> a -> c

وهنا لدينا

map f :: [a] -> [[b]]

و

concat :: [[b]] -> [b]

وهكذا نحن في نهاية المطاف مع

concat . map f :: [a] -> [b]

وونوع (.) يمكن أن يكتب

و:: ([[ب]] -> [ب]) - (.)> ([أ] -> [[ب]]) -> [أ] -> [ب]

إذا كان لنا أن استخدام concat . map f xs، كنا نرى أن

map f xs :: [[b]]

وحتى لا يمكن استخدامها مع (.). (النوع لا بد أن يكون () :: (أ -> ب) -> و-> ب

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top