2012-03-09 7 views
3

РассмотримКак использовать стрелки здесь?

foldr (\x (a,b) -> (a || x==2, b || x==7)) (False,False) [1..6] 
--(True,False) 

Игнорируя тот факт, что это может быть написано легко с помощью elem, у меня есть стойкое ощущение, что я мог бы трудоустроить Arrow синтаксис для упрощения лямбды, я просто не могу получить это права.

Можно ли упростить эту лямбду, используя стрелки? И есть ли у вас общие подсказки о том, как «видеть», когда стрелки могут работать, и как найти правильное выражение?

+1

Эдвард Kmett освободил меня от необходимости заботиться о стрелкам три недели флаговых o [с этими комментариями к блогу Брэндона Симмонса] (http://brandon.si/code/categories-that-want-to-be-arrows/#comment-437318026). –

+1

@ DanielLyons тем не менее, типичные комбинации стрелок '&&&', '|||' и '***' могут быть полезны из-за экземпляра функции стрелки. –

+0

Согласовано. Я просто не думаю, что выигрыш по-настоящему, полностью понимая их, оправдывает боль. –

ответ

7

Вытащите вычисление из foldr -

ghci> :m +Control.Arrow 
ghci> any (==2) &&& any (==7) $ [1..6] 
(True,False) 

Но если вы хотите, чтобы убедиться, что вы только обход списка раза , попробуйте использовать bifunctor package:

ghci> :m +Data.Bifunctor +Data.Bifunctor.Apply 
ghci> foldr (bilift2 (||) (||) . ((==2) &&& (==7))) (False, False) [1..6] 
(True,False) 
+2

Или короче: 'elem 2 &&& elem 7 $ [1..6]' – Landei

6
foldr (\x -> (|| x==2) *** (|| x==7)) (False,False) [1..6] 

Я не думаю, что вы можете абстрагировать x со стрелками.

Edit: хорошо, кажется, что вы можете:

foldr (uncurry (***) . (((||) . (==2)) &&& ((||) . (==7)))) (False,False) [1..6] 
+3

Является ли '(||)' пустое выражение, окруженное банановыми скобками? ;-) – Andre

+1

Если значение действительно необходимо, вы всегда можете дать ему больше пробелов: '(||)'. Но использование 6 символов для обозначения 2-символьного оператора является жестоким. –

+0

Даже если решение выглядит не очень мило, я буду держать 'трюк (***)' трюк в виду. Благодаря! – Landei