ارتباك حول الكريات والأسلوب المجاني نقطة في Haskell

StackOverflow https://stackoverflow.com/questions/907306

  •  05-09-2019
  •  | 
  •  

سؤال

كنت أحاول تنفيذ الوظيفة

every :: (a -> IO Bool) -> [a] -> IO Bool 

الذي كان الموضوع ل هذا السؤال. وبعد حاولت القيام بذلك دون recursion صريحة. وبعد لقد توصلت إلى الكود التالي

every f xs = liftM (all id) $ sequence $ map f xs

لم تنجح وظيفتي لأنها لم تكن كسولا (والتي كانت مطلوبة في السؤال)، لذلك لا توجد upvotes هناك :-).

ومع ذلك، لم أتوقف هناك. حاولت أن أجعل الوظيفة خال من النقطة بحيث يكون أقصر (وربما أكثر برودة). منذ الحجج f و xs هي آخر منها في التعبير، لقد أسقطتها للتو:

every = liftM (all id) $ sequence $ map 

لكن هذا لم ينجح كما هو متوقع، في الواقع لم ينجح على الإطلاق:

 1 من 1] ترجمة الرئيسية (STK.HS، المفسر) STK.HS: 53: 42: تعذر مطابقة النوع المتوقع `[MA] ضد نوع الاستنتاج `(A1 -> B) -> [A1] -> [B] "في الحجة الثانية من` ($) "، وهي" خريطة "في الحجة الثانية من` ($)، وهي "تسلسل خريطة $" في التعبير: فشل LIFTM (كل المعرف) $ خريطة $ ، وحدات محملة: لا شيء.

لماذا هذا؟ كنت تحت الانطباع بأنه كان من الممكن ببساطة قطرة حجج وظيفة زائدة، والتي هي أساسا ما يدور حوله.

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

المحلول

تعريف $ هو

f $ x = f x

دعونا قوسا تماما وظيفتك:

every f xs = (liftM (all id)) (sequence ((map f) xs))

ونسخة الكتر الخاصة بك:

every = (liftM (all id)) (sequence map)

كما لاحظت، هذه ليست متطابقة. يمكنك فقط إسقاط الوسائط الوظيفية الزائدة عندما تكون آخر شيء مطبق. علي سبيل المثال،

f x = g c x

في الواقع

f x = (g c) x

وتطبيق (GC) إلى x يأتي آخر، حتى تتمكن من الكتابة

f = g c

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

f $ g $ x

أي ما يعادل

(f . g) $ x

علي سبيل المثال،

every f xs = liftM (all id) $ sequence $ map f xs

يمكن أن تصبح

every f xs = (liftM (all id) . sequence . map f) xs

عند أي نقطة يمكنك إسقاط XS:

every f = liftM (all id) . sequence . map f

القضاء على حجة F أكثر صعوبة، لأنه يتم تطبيقه قبل مشغل التركيب. دعونا نستخدم تعريف النقطة من http://www.haskell.org/haskellwiki/pointfree.:

dot = ((.) . (.))

مع النقاط، هذا هو

(f `dot` g) x = f . g x

وهذا هو بالضبط ما نحتاجه لجعل كل نقطة خالية من النقاط بالكامل:

every = (liftM (all id) . sequence) `dot` map

للأسف، بسبب القيود المفروضة في نظام Haskell، يحتاج هذا المرء إلى توقيع نوع صريح:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top