Можно ли использовать синтаксический сахар для брекетинга для аппликативного функтора?
В 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
не должно быть затенено вашим кодом, иначе это не сработает. Не знаете, насколько велика сделка, это лично).