Is it possible to use a bracketing syntactic sugar for an applicative functor?

自作多情 提交于 2019-12-03 04:49:56

This is pretty easy to implement in Template Haskell by using the haskell-src-meta package to parse the Haskell expression in the quasi-quotation.

{-# 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"

Note that due to how Template Haskell works, you can't use the quasiquoter from the same file where it's defined, so save the above to its own module.

Testing in GHCi

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

I think this is what you are looking for. If I remember correctly there has also been a discussion on the haskell-cafe mailing list regarding this style of applicative applications.

The Template Haskell approach to this was written by Matt Morrow and then maintained by me, in the applicative-quoters package. You use it as [i| f x y z |], so it's reasonably close to McBride and Paterson's original idea.

(Possible drawback: the name i should not be shadowed by your code, else it won't work. Not sure how big a deal this is, personally).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!