Можно ли использовать синтаксический сахар для брекетинга для аппликативного функтора?

В McBride и Paterson "Аппликационное программирование с эффектами" они вводят прекрасный синтаксический сахар для поднятия чистой функции:

[| f x y z |]

для

f <$> x <*> y <*> z

и я вспоминаю кого-то в другом месте с помощью li f w x y z il или il f v w x y z li, и я подумал/надеялся, что это может быть связано с тем, что он может быть определен с использованием некоторой существующей языковой функции и хитрого определения li и il.

Я не могу найти никакой ссылки на это за пределами статьи и предполагая, что [| и |] вряд ли появятся в ghc в ближайшее время, возможно ли реализовать li и il как-то? Я не могу придумать разумный тип для них, поэтому я предполагаю, что мне понадобится шаблон Haskell или аналогичный, но не знаю, достаточно ли для этого. [af| f x y ] будет хорошо, но я не знаю, возможно ли это до того, как я начну его пытаться, и, конечно, нужна помощь, если это возможно.

Ответ 1

Это довольно легко реализовать в Template Haskell с помощью пакета haskell-src-meta для синтаксического анализа выражения Haskell в квазикомиссии.

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Language.Haskell.Meta (parseExp)

import Control.Applicative ((<*>), (<$>))

af = QuasiQuoter
    { quoteExp  = parseAf
    , quotePat  = undefined
    , quoteType = undefined
    , quoteDec  = undefined
    }

parseAf :: String -> Q Exp
parseAf s = case parseExp s of
    Right ex -> applyExp ex
    Left err -> fail err

applyExp :: Exp -> Q Exp
applyExp (AppE [email protected](AppE _ _) a) = [|$(applyExp f) <*> $(return a)|]
applyExp (AppE f a) = [|$(return f) <$> $(return a)|]
applyExp _ = fail "invalid expression in af"

Обратите внимание, что из-за того, как работает Template Haskell, вы не можете использовать квазикодировщик из того же файла, где он определен, поэтому сохраните выше в своем собственном модуле.

Тестирование в GHCi

*Main> :set -XTemplateHaskell
*Main> :set -XQuasiQuotes
*Main> [af|(+) (Just 3) (Just 8)|]
Just 11
*Main> [af|(+) (Just 6) Nothing|]
Nothing

Ответ 2

Я думаю, этот - это то, что вы ищете. Если я правильно помню, также был обсужден список рассылки haskell-cafe в отношении этого стиля прикладных приложений.

Ответ 3

Подход шаблона Haskell к этому был написан Мэттом Морроу, а затем поддержан мной в пакете аппликативных-котировок. Вы используете его как [i| f x y z |], поэтому он достаточно близок к оригинальной идее Макбрайда и Патерсона.

(Возможный недостаток: имя i не должно быть затенено вашим кодом, иначе это не сработает. Не знаете, насколько велика сделка, это лично).