在McBride and Paterson's 'Applicative programming with effects'中,他们为解除纯粹的功能引入了一些可爱的语法糖:
[| 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中很快出现,是否可以实现{{ 1}}和li
不知何故?我不能为他们想出一个合理的类型,所以我假设我需要模板Haskell或类似,但不知道几乎足以实现这一点。 il
会很好,但我不知道在我开始尝试它之前是否可能,如果是的话,肯定需要帮助。
答案 0 :(得分:16)
我认为this正是您所寻找的。如果我没记错的话,还有关于这种应用方式的haskell-cafe邮件列表的讨论。
答案 1 :(得分:14)
通过使用haskell-src-meta包来解析准引用中的Haskell表达式,可以很容易地在Template 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 f@(AppE _ _) a) = [|$(applyExp f) <*> $(return a)|]
applyExp (AppE f a) = [|$(return f) <$> $(return a)|]
applyExp _ = fail "invalid expression in af"
请注意,由于模板Haskell的工作原理,您无法使用定义它的同一文件中的quasiquoter,因此请将上述内容保存到自己的模块中。
在GHCi中进行测试
*Main> :set -XTemplateHaskell
*Main> :set -XQuasiQuotes
*Main> [af|(+) (Just 3) (Just 8)|]
Just 11
*Main> [af|(+) (Just 6) Nothing|]
Nothing
答案 2 :(得分:8)
模板Haskell的方法是由Matt Morrow编写的,然后由我在applicative-quoters package中维护。您将其用作[i| f x y z |]
,因此它与McBride和Paterson的原创理念相当接近。
(可能的缺点:名称i
不应该被您的代码遮蔽,否则它将无法正常工作。不确定这是多么大的交易,个人而言。