2

わかりました、私はおそらくこれを間違ってやっていますが、それは私の髪を引っ張っています. やりたいことが見つからない

この擬似コードを取得します

my_function left right
    = another_function new_left new_right (fourth_function new_left new_right)
        where new_left = if some_condition then left else third_function left
            new_right = if some_condition then third_function right else right

some_condition の再チェックを避けるにはどうすればよいですか? some_conditionまた、構成内の別の変数として保存することについて話しているのではありませんwhereletsIの中に入れると、ifを複製しin another_function new_left new_rightます。

命令型言語では、次のようなことができます

int new_left;
int new_right;
if (condition) {
    new_left = left;
    new_right = third_function(right);
} else {
    new_left = third_function(left);
    new_right = right;
}
return another_function(new_left, new_right, fourth_function(new_left, new_right));

関数型言語では、物事を順番に行うのではなく、式の構成として考える必要があることを知っているので、元の疑似コードを DRY になるように記述する方法を探しています。そして、それは単純で比較的一般的なケースのようです。

編集

混乱させて申し訳ありません。third_function left/right値を 2 回使用する必要があるため、インライン化できません(更新された疑似コード)。そしてfourth_function中で動かせないanother_function

4

3 に答える 3

5

どうですか

my_function left right | somecondition = 
                         another_function left (third_function right)
                       | otherwise     =
                         another_function (third_function left) right

新しい編集で

my_function left right = ...
  where (new_left, new_right) | somecondition = (left, third_function right)
                              | otherwise     = (third_function left, right)
于 2013-09-30T20:04:45.610 に答える
0

単純な関数プログラミングを使用するだけであれば、はい、「if」を使用できます。

「左」が少ない場合は、モナドまたはモノイド ( Maybe aEither a bAny aAll a...) が適しています。

foo = do
   if cond1 then Just smths1 else Nothing
   if cond2 then Just smths2 else Nothing
   if cond2 then Just smths2 else Nothing
   if cond2 then Just smths2 else Nothing
   if cond2 then Just smths2 else Nothing

「左」と「右」がたくさんある場合は、矢印が適しています。

foo = proc (l,r) -> do
    nl <- (if cond1 then idA else arr . foo1)   -< l
    nr <- (if cond2 then arr . foo2 else idA )  -< r
    ...
于 2013-09-30T22:16:33.153 に答える
0

おそらく最も速い方法は

my_function left right
      = uncurry another_function $ if some_condition
                                    then (left, third_function right)
                                    else (third_function left, right)

しかし、jozefg の提案はかなりクリーンな IMO です。


更新された質問については、結果を再利用するときは、実際に名前付き変数にするのが一般的に良いですが、jozefg は問題でそれを行う方法を示しました。しかし(あなたの命令的なものへの橋渡しも):Haskellにはモナドがあり、命令的なもの(そしてもちろんそれ以上のもの)に使用できます。あなたの場合、Readerモナド、別名関数がトリックを行います:

import Control.Monad.Instances

my_function left right = 
        ( uncurry fourth_function >>= flip (uncurry another_function) )
         $ if some_condition
            then (left, third_function right)
            else (third_function left, right)

しかし、このスタイルの可読性にはかなり疑問があります。

arrowsのヘルパーを使用すると少し良くなりますが、その関数も特殊なケースです。

import Control.Arrow

my_function = curry $
        ( uncurry fourth_function >>= flip (uncurry another_function) )            
        . (if some_condition then second else first) third_function
于 2013-09-30T20:04:33.220 に答える