6

Can you convert

-- tupleUnfold :: forall a. ((forall b. a -> b)) -> a -> ((b))
tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
  xs <- forM [1 .. n] (const . newName $ "x")
  y <- newName "y"
  let y' = varE y
      g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
      (ps, es) = foldl' g ([], []) xs
  lamE [tupP ps, varP y] (tupE es)

to pointfree style while maintaining clarity (I know of the program 'pointfree', but would prefer not to obfuscate the code even more)?

Either way, what changes could be made to improve the style of the function, or otherwise makes its intent clearer? The function is intended to be used as below.

$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)

What are some better naming conventions to use (see the ps, ps', es, and es' variables)?

4

3 回答 3

5

这就是我得到的。需要Control.Arrow (&&&)Control.Applicative (<$>)

tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
    y <- newName "y"
    (ps,es) <- unzip . map (varP &&& (`appE` varE y) . varE) 
                <$> replicateM n (newName "x")
    lamE [tupP ps, varP y] (tupE es)

在不让它完全无法理解的情况下,不能再细化它了。

编辑虽然不是免费的,但这是我能做到的最清楚的。需求Data.Function (on)

tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
    y <- newName "y"
    xs <- replicateM n (newName "x")
    let exps = tupE $ zipWith appVars xs (repeat y)
        pats = tupP $ map varP xs
    lamE [pats, varP y] exps
  where
    appVars = appE `on` varE
于 2010-11-21T01:39:30.073 回答
1

有点难以理解(尝试从右到左阅读):

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((:[varP y]) . tupP *** tupE) . unzip .   
   map (varP &&& (`appE` varE y) . varE) <$> replicateM n (newName "x")

编辑
混合箭头和功能组合进行处理

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((tupP >>> (:[varP y])) *** tupE) . unzip .
    map (varP &&& (varE >>> (`appE` varE y))) <$> replicateM n (newName "x")

并且主要使用箭头(从左到右读取处理函数)

tupleUnfold n = do
  y <- newName "y"
  (map (varP &&& (varE >>> (`appE` varE y))) >>> unzip >>>
    ((tupP >>> (:[varP y])) *** tupE) >>> uncurry lamE) <$> replicateM n (newName "x")

注意箭头函数(>>>)等价于翻转 (.)

于 2010-11-22T05:57:48.843 回答
0

我个人认为这已经很清楚了,但是这个怎么样:

tupleUnfold :: Int -> ExpQ
tupleUnfold = mapM (const . newName $ "x") . enumFromTo 1 >=> \xs -> do
    y <- newName "y"
    let y' = varE y
        g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
        f ps = lamE [tupP ps, varP y] . tupE
    uncurry f $ foldl' g ([],[]) xs

Kleisli 组合运算符>=>(来自 Control.Monad)对于创建无点单子函数很有用。

于 2010-11-21T01:11:48.507 回答