您可以转换

-- 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)
同时保持

要pointfree风格清晰度(我知道程序“pointfree”的,但不希望更加混淆代码)?

无论哪种方式,可以作出什么样的变化,以改善功能的风格,或以其他方式使得其意图更清晰?功能旨在被用作以下。

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

什么是一些更好的命名约定来使用(见PS,PS',ES和ES'变量)?

有帮助吗?

解决方案

下面是我得到的。需要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

其他提示

稍微难以理解(尝试从右向左阅读):

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")

请注意箭头函数的(>>>)相当于为翻转(。)

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

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)是用于创建pointfree单子功能是有用的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top