سؤال

من وقت لآخر ، أتعثر حول المشكلة التي أريد التعبير عنها "الرجاء استخدام الوسيطة الأخيرة مرتين" ، على سبيل المثال لكتابة نمط pointfree أو تجنب lambda. على سبيل المثال

sqr x = x * x

يمكن أن تكتب كما

sqr = doubleArgs (*) where
   doubleArgs f x = f x x

أو النظر في هذه الوظيفة أكثر تعقيدًا قليلاً (مأخوذة من هذا السؤال):

ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)

يمكنني كتابة هذا الكود pointfree إذا كانت هناك وظيفة مثل هذه:

ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
     dup f f1 f2 x = f (f1 x) (f2 x)

لكن بما أنني لا أجد شيئًا مثل Doubleargs أو DUP في Hoogle ، لذلك أعتقد أنني قد أفتقد خدعة أو تعبيرًا هنا.

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

المحلول

من Control.Monad:

join :: (Monad m) -> m (m a) -> m a
join m = m >>= id

instance Monad ((->) r) where
    return = const
    m >>= f = \x -> f (m x) x

التوسع:

join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
       = \x -> id (f x) x
       = \x -> f x x

إذن أجل، Control.Monad.join.

أوه ، ولثالتك على سبيل المثال ، هل حاولت استخدام الترميز التطبيقي (من Control.Applicative):

ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails

(أنا أيضا لا أعرف لماذا الناس مولعين جدا a ++ (x:b) بدلاً من a ++ [x] ++ b... إنها ليست أسرع - سوف يعتني به Inliner - والأخير أكثر تماثلًا! اوه حسناً)

نصائح أخرى

غالبًا ما يسمى ما تسميه "Doubleargs" DUP - إنه Combinator W (الذي يسمى Warbler في السخرية من الطائر المحاكي) - "The Elementary Duplicator".

ما تسميه "DUP" هو في الواقع combinator "starling-prime".

لدى Haskell "أساس combinator" صغير إلى حد ما ، راجع البيانات مثيل وظيفي ، Lifta2 & LiftM2 هما Starling-Prime). لا يبدو أن هناك الكثير من الحماس في المجتمع لتوسيع البيانات. وظيفية ، لذلك في حين أن المجموعتين ممتعة بشكل جيد ، فقد أصبحت براغمات تفضيلها في المواقف التي لا يتوفر فيها المشابك بشكل مباشر.

إليك حل آخر للجزء الثاني من سؤالي: الأسهم!

import Control.Arrow

ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))

ال &&& ("Fanout") يوزع وسيطة على وظيفتين وإرجاع زوج النتائج. >>> ("ثم") يعكس ترتيب تطبيق الوظيفة ، والذي يتيح أن يكون لديك سلسلة من العمليات من اليسار إلى اليمين. second يعمل فقط في الجزء الثاني من الزوج. بالطبع تحتاج إلى uncurry في النهاية لتغذية الزوج في وظيفة تتوقع وسيطتين.

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