Рассматриваются функции типа a -> b -> c
и применяемые значения a1, a2 :: (Applicative f) => f a
.
Я хочу построить функцию, которая может быть применена к функциям типа a -> b -> c
для получения значений типа Applicative f :: f c
. Я могу сделать это следующим образом:
g :: (Applicative f) => (a -> b -> c) -> f c
g = \f -> f <$> a1 <*> a2
(Явный лямбда является преднамеренным, как я рассматривает возможность строительства этой функции на любом уровне, а не только верхний уровень).
Если я пытаюсь написать g
в точке свободного стиля:
g = (<$> a1 <*> a2)
я получаю следующее Ошибка компиляции:
The operator `<$>' [infixl 4] of a section
must have lower precedence than that of the operand,
namely `<*>' [infixl 4]
in the section: `<$> gen1 <*> gen2'
Я мог написать эту точку свободной реализации:
g = flip (flip liftA2 a1) a2
но я чувствую, что это le ss readable, и проще реорганизовать реализацию на основе функции на основе infix, например, добавить другой аргумент, чем изменить выше, чтобы использовать liftA3
.
можно написать цепочку композиций:
g = (<*> a2) . (<$> a1)
Это достигается точка свободного стиля и просто добавить аргументы - но они получают предваряется на левой, а не добавляется справа, так вы теряете соответствие с типом функции (a -> b -> c)
. Более того, с большим количеством аргументов вы получаете гораздо более длинное выражение, чем просто использование лямбда, как в первой реализации.
Итак, есть ли хороший, простой способ написать раздел, который я хочу, или я застрял с лямбдой?
в Scala вы можете иметь '_ <$> в <*> b' но Haskell не имеет такой синтаксис. –
@ErikAllik Это интересный синтаксис! Интересно, кто-то написал для него расширение шаблона-haskell. Это было бы здорово. – AJFarmar
, но '_' уже были сделаны набранными отверстиями; возможно, что-то подобное; хотя синтаксис лямбда довольно хорош. –