pointfreeスタイルとnon-unaryアリティを簡単に組み合わせることができるかどうかはわかりません。 が結果と構成機能のタイプでなければなりません最初に何を考える:
// Compose: (B -> C) -> (A -> B) -> A -> C
const compose = f => g => x => f(g(x))
// Add: A -> A -> A
const add = x => y => x + y
// Mul: A -> A -> A
const mul = x => y => x * y
// Add1: A -> A
const add1 = add(1)
// Add1AndMul: A -> A -> A
// because:
// Add1: A -> A
// Mul: A -> A -> A
const add_1_and_mul = compose(mul)(add1)
// Mul4: A -> A
const mul_4 = add_1_and_mul(3)
const result = mul_4(5) //> 20
RAMDAはそうあなたがcompose
のまわりでそれをラップした関数のカリー化を取り除くことができuncurryN
を持っています。
const add_1_and_multiply = R.uncurryN(2, R.compose(R.multiply, R.add(1)))
let result2 = add_1_and_multiply(3, 5) //> 20
以前の機能とそれを構成する必要がある「チェーン」に別の機能を追加します。
// Add1AndMul: A -> A -> A
const add1_mul = compose(mul)(add1)
これは私たちの希望する署名です。
// 1 2 3
// Add1AndMulAndAdd: A -> A -> A -> A
// which is: | | |
// Add1: A -> A | |
// Mul: A -> A -> A |
// Add: A -> A -> A
だから何とか我々はそれらのいずれかの "ポイント" のないとを渡す必要があります。 のは、単純な構図を試してみて、それを分析してみましょう:コンの
let add1_mul_add = compose(add)(add1_mul)
思い出してくれるの署名:(E -> F) -> (D -> E) -> D -> F
! はステップでそれを分析:我々は、代わりに(E -> F)
(E -> F )
(A -> A -> A)
の私達のadd
関数のシグネチャを供給
我々は
E = A
F = A -> A
我々は(D -> E)
とadd1_mul
に同じことを行うと結論します (D -> E )
(A -> A -> A)
我々は
D = A
E = A -> A
と結論しかし、我々はすでにそこに矛盾を見ることができます! 手順2の結論は、手順1の結論に矛盾します。 E
は、同時にA
とA -> A
になることはできません。
したがって、add
とadd1_mul
とadd1_mul_add
はエラーになります。
問題を回避して、ポイントフリースタイルの約束を破って修正してみましょう。
const add1_mul_add = x => compose(add)(add1_mul(x))
私はいくつかのルールを破ると私のポイントを説明するために、コードで署名をミックスするつもりです:
x -> (A -> A -> A) -> (x -> A -> A) -> A -> A -> A
||
\/
x -> (A -> A -> A) -> (A -> A) -> A -> A -> A
(E -> F ) -> (D -> E) -> D -> F
だから、我々は正しいコン署名を持って! x
変数を削除してpointfreeに戻すにはどうすればよいですか? 私たちはあなたの古きよき機能の構成のような、明らかなパターンを探すことができます!
f(g(x)) => compose(f)(g)
そして、私たちは私たちの新しいadd1_mul_add
でこのパターンを見つける -
f = compose(add)
g = add1_mul
f(g(x)) = compose(add)(add1_mul(x))
そして、我々はそれがpointfreeする削減し、我々は新しいadd1_mul_add
機能だ:
const add1_mul_add = compose(compose(add))(add1_mul)
でもねえを - 私達ができますそれをさらに減らしてください!
const add1_mul_add = compose(compose)(compose)(add)(add1_mul)
また、haskellには既にThe Owl
という名前で存在するものが見つかりました。
我々は単にJavaScriptでそれを定義することができます。
const owl = compose(compose)(compose)
しかし、今、チェーン内のすべての新機能で、あなたはフクロウのオペレータの上位を作成する必要があります。
const owl2 = compose(compose)(owl)
const add1_mul_add_mul = owl2(mul)(add1_mul_add)
const owl3 = compose(compose)(owl2)
const add1_mul_add_mul_add = owl3(add)(add1_mul_add_mul)
だから私は本当にpointfreeスタイルで単項あなたの機能を有するお勧めします。または、リストのような他の構文を使用してください。
const actions = [ add, mul, add, mul ]
const values = [ 1, 2, 3, 4 ]
const add_mul_add_mul = (...values) => zip(actions, values).reduce((acc, [action, value]) => action(acc, value), 0)
'multiply(y、add(1、x))'の代わりに 'multiply(add(1、x)、y)'を使用してみてください。 compose(R.multiply、R.add(1)) ' – Bergi
@Bergiこれはまさに私の答えで結論づけたものです。 –