模板Haskell:如何提取函数的参数个数?

Alf*_*oli 9 haskell template-haskell

我有一个函数给出了Name一个函数它增加它,产生另一个函数应用于其他一些东西(细节不太相关):

mkSimple :: Name -> Int -> Q [Dec]
mkSimple adapteeName argsNum = do
  adapterName <- newName ("sfml" ++ (capitalize . nameBase $ adapteeName))
  adapteeFn <- varE adapteeName
  let args = mkArgs argsNum
  let wrapper = mkApply adapteeFn (map VarE args)
  -- generates something like SFML $ liftIO $ ((f a) b) c)
  fnBody <- [| SFML $ liftIO $ $(return wrapper) |]
  return [FunD adapterName [Clause (map VarP args) (NormalB fnBody) []]]

  where
    mkArgs :: Int -> [Name]
    mkArgs n = map (mkName . (:[])) . take n $ ['a' .. 'z']


-- Given f and its args (e.g. x y z) builds ((f x) y) z)
mkApply :: Exp -> [Exp] -> Exp
mkApply fn [] = fn
mkApply fn (x:xs) = foldr (\ e acc -> AppE acc e) (AppE fn x) xs
Run Code Online (Sandbox Code Playgroud)

这是有效的,但从外部传递适配器功能所具有的args数量是很繁琐的.有一些TH函数来提取args的数量?我怀疑它可以通过reify实现,但我不知道如何.

谢谢!

jbe*_*man 6

当然,你应该可以做到

do (VarI _ t _ _) <- reify adapteeName
   -- t :: Type
   -- e.g. AppT (AppT ArrowT (VarT a)) (VarT b)
   let argsNum = countTheTopLevelArrowTs t
   ...

   where
     countTheTopLevelArrowTs (AppT (AppT ArrowT _) ts) = 1 + countTheTopLevelArrowTs
     countTheTopLevelArrowTs _ = 0
Run Code Online (Sandbox Code Playgroud)

以上只是我的想法,可能不太正确.

  • 您可能还需要扩展类型同义词. (3认同)
  • 这是不明确的..在一个函数中有多少个参数有签名`Arrow a => Int - > Int Int`?多态性意味着总会有一些歧义. (2认同)