簡體   English   中英

如何為monad實現通用提升功能?

[英]How to implement a generic lift function for monads?

我有一堆arity意識升力功能:

 const chain = f => xs => xs.reduce((acc, x) => acc.concat(f(x)), []); const of = x => [x]; const add = (x, y) => x + y; const liftM2 = (chain, of) => f => m1 => m2 => chain(x => chain(y => of(f(x, y))) (m2)) (m1); console.log(liftM2(chain, of) (add) ([2]) ([3])); // [5] 

是否可以實現相應的通用升力功能?

const liftM = (chain, of) => f => (...ms) => ...

我想這是一個遞歸算法,但我無法繞過它。

是的,你可以在ms遞歸遞歸,但我想折疊更合適:

const lift = (chain, of) => f => (...ms) =>
  ms.reduceRight((acc, m) =>
    (...xs) => chain(x => acc(...xs, x))(m)
  , (...xs) => of(f(...xs))
  )()

這是遞歸程序,如果你仍然對它感興趣 -

 const chain = f => xs => xs .reduce ( (acc, x) => acc .concat (f (x)) , [] ) const of = x => [ x ] const add = (x, ...xs) => x === undefined ? 0 : x + add (...xs) const lift = (chain, of) => f => (...ms) => { const loop = (xs, [ m, ...rest ]) => m === undefined ? of (f (...xs)) : chain (x => loop ([ ...xs, x ], rest)) (m) return loop ([], ms) } const print = (...xs) => xs .forEach (x => console .log (JSON .stringify (x))) print ( lift (chain, of) (add) () , lift (chain, of) (add) ([ 1 ]) , lift (chain, of) (add) ([ 1 ], [ 2 ]) , lift (chain, of) (add) ([ 1 ], [ 2 ], [ 3 ]) , lift (chain, of) (add) ([ 1 ], [ 2 ], [ 3 ], [ 4 ]) ) // [ 0 ] [ 1 ] [ 3 ] [ 6 ] [ 10 ] 

我們可以修改lift ,這取決於用戶提供的函數的arity,例如這個雙參數函數add2 -

const add2 = (x, y) =>
  x + y

lift (chain, of) (add2) ([ 1 ]) ([ 2 ])
// [ 3 ]

lift (chain, of) (add2) ([ 1, 1 ]) ([ 2, 2, 2 ])
// [ 3, 3, 3, 3, 3, 3 ]

或者這個三參數函數, add3 -

const add3 = (x, y, z) =>
  x + y + z

lift (chain, of) (add3) ([ 1 ]) ([ 2 ]) ([ 3 ])
// [ 6 ] 

lift (chain, of) (add3) ([ 1, 1 ]) ([ 2, 2, 2 ]) ([ 3, 3, 3, 3 ])
// [ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 ]

這是實施 -

const curry = (f, n = f.length) =>
{ const loop = (xs, n) =>
    n === 0
      ? f (...xs)
      : x => loop ([ ...xs, x ], n - 1)
  return loop ([], n)
}

const lift = (chain, of) => f =>
{ const loop = (xs, [ m, ...rest ]) =>
    m === undefined
      ? of (f (...xs))
      : chain (x => loop ([ ...xs, x ], rest)) (m)
  return curry
    ( (...ms) => loop ([], ms)
    , f.length
    )
}

展開下面的代碼段以在您自己的瀏覽器中驗證結果 -

 const chain = f => xs => xs .reduce ( (acc, x) => acc .concat (f (x)) , [] ) const of = x => [ x ] const curry = (f, n = f.length) => { const loop = (xs, n) => n === 0 ? f (...xs) : x => loop ([ ...xs, x ], n - 1) return loop ([], n) } const lift = (chain, of) => f => { const loop = (xs, [ m, ...rest ]) => m === undefined ? of (f (...xs)) : chain (x => loop ([ ...xs, x ], rest)) (m) return curry ((...ms) => loop ([], ms), f.length) } const print = (...xs) => xs .forEach (x => console .log (JSON .stringify (x))) const add2 = (x, y) => x + y const add3 = (x, y, z) => x + y + z print ( lift (chain, of) (add2) ([ 1 ]) ([ 2 ]) , lift (chain, of) (add2) ([ 1, 1 ]) ([ 2, 2, 2 ]) , lift (chain, of) (add3) ([ 1, 1 ]) ([ 2, 2, 2 ]) ([ 3, 3, 3, 3 ]) ) // [ 3 ] // [ 3, 3, 3, 3, 3, 3 ] // [ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 ] 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM