为什么模板Haskell会添加意外的对象?

我有以下几点:

import Control.Applicative
import Control.Monad
import Language.Haskell.TH


mkExp :: [Name] -> ExpQ
mkExp (name:[]) = [| ZipList $(varE name) |]
mkExp (name:names) = [| ZipList $(varE name) <*> $(mkExp names) |]

zipN :: Int -> ExpQ
zipN n = do
  names <- mapM newName $ replicate n "x"
  fn <- newName "f"
  let vps = map varP (fn:names)
  lamE vps $ [| $(varE fn) <$> $(mkExp names) |]

我想要$(zipN 2)生成:

f x y -> f <$> ZipList x <*> ZipList y

因此它具有类型(a -> b -> c) -> [a] -> [b] -> [c] 。 但是,从-ddump-splices输出并滤除噪音,我发现$(zipN 2)会生成:

f x y -> f <$> ((ZipList x) <*> (ZipList y))

与类型(a -> b) -> [a1 -> a] -> [a1] -> ZipList b 。 同样, $(zipN 3)生成:

f x1 x2 x3 -> (f <$> ((ZipList x1) <*> ((ZipList x2) <*> (ZipList x3)))

所以它看起来像$([|...|])每个实例被替换为(...)而不是... ,这对我来说是令人惊讶的,因为文档似乎认为$( )[| |] [| |] “取消。”

为什么模板Haskell生成这个AST,我能做些什么来用正确的类型从它获得一个函数?


<$><*>都是关联的。 你是正确的关联他们。

您可以构建表达式,以便运算符是左侧关联的。

mkExp' :: ExpQ -> [Name] -> ExpQ
mkExp' acc [] = acc
mkExp' acc (name:names) = mkExp'' [| $(acc) <$> ZipList $(varE name) |] names
    where
        mkExp'' acc [] = acc
        mkExp'' acc (name:names) = mkExp'' [| $(acc) <*> ZipList $(varE name) |] names

zipN :: Int -> ExpQ
zipN n = do
  names <- mapM newName $ replicate n "x"
  fn <- newName "f"
  let vps = map varP (fn:names)
  lamE vps $ mkExp' (varE fn) names
链接地址: http://www.djcxy.com/p/33183.html

上一篇: Why does Template Haskell add unexpected parens?

下一篇: Why Template Haskell uses AST