6

変換できますか

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

明快さを維持しながらポイントフリースタイルにする(私はプログラム「ポイントフリー」を知っていますが、コードをさらに難読化したくない)?

いずれにせよ、関数のスタイルを改善するために、またはその意図をより明確にするために、どのような変更を加えることができますか?この機能は、以下のように使用することを目的としています。

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

使用するのに適した命名規則は何ですか(ps、ps'、es、およびes'変数を参照)。

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 に答える