我将提供这篇文章作为对@ftor实用答案的补充 - 这个代码片段展示了如何使用通用函数来实现这种结果。
const identity = x =>
x
const comp = ( f, g ) =>
x => f ( g ( x ) )
const compose = ( ...fs ) =>
fs.reduce ( comp, identity )
const append = ( xs, x ) =>
xs.concat ( [ x ] )
const transduce = ( ...ts ) => xs =>
xs.reduce ( compose ( ...ts ) ( append ), [] )
const when = f =>
k => ( acc, x ) => f ( x ) ? k ( acc, x ) : append ( acc, x )
const mapper = f =>
k => ( acc, x ) => k ( acc, f ( x ) )
const data0 =
[ { id: 1, remove: true }
, { id: 2, remove: true }
, { id: 3, remove: true }
]
const data1 =
transduce ( when ( x => x.id === 2)
, mapper ( x => ( { ...x, remove: false } ) )
)
(data0)
console.log (data1)
然而,我认为我们可以通过更通用的行为来改进when
,我们只需要一些虚构类型Left
和Right
的帮助-在此摘录后展开完整的代码片段
const Left = value =>
({ fold: ( f, _ ) =>
f ( value )
})
const Right = value =>
({ fold: ( _, f ) =>
f ( value )
})
// a more generic when
const when = f =>
k => ( acc, x ) => f ( x ) ? k ( acc, Right ( x ) ) : k ( acc, Left ( x ) )
// mapping over Left/Right
mapper ( m =>
m.fold ( identity // Left branch
, x => ( { ...x, remove: false } ) // Right branch
) )
const Left = value =>
({ fold: ( f, _ ) =>
f ( value )
})
const Right = value =>
({ fold: ( _, f ) =>
f ( value )
})
const identity = x =>
x
const comp = ( f, g ) =>
x => f ( g ( x ) )
const compose = ( ...fs ) =>
fs.reduce ( comp, identity )
const append = ( xs, x ) =>
xs.concat ( [ x ] )
const transduce = ( ...ts ) => xs =>
xs.reduce ( compose ( ...ts ) ( append ), [] )
const when = f =>
k => ( acc, x ) => f ( x ) ? k ( acc, Right ( x ) ) : k ( acc, Left ( x ) )
const mapper = f =>
k => ( acc, x ) => k ( acc, f ( x ) )
const data0 =
[ { id: 1, remove: true }
, { id: 2, remove: true }
, { id: 3, remove: true }
]
const data1 =
transduce ( when ( x => x.id === 2 )
, mapper ( m =>
m.fold ( identity
, x => ( { ...x, remove: false } )
) )
)
(data0)
console.log (data1)
因此,您的最终函数可能看起来像这样
const updateWhen = ( f, records, xs ) =>
transduce ( when ( f )
, mapper ( m =>
m.fold ( identity
, x => ( { ...x, ...records } )
) )
) ( xs )
你可以在你的 reducer 中这样调用它
const BakeryReducer = ( donuts = initState , action ) =>
{
switch ( action.type ) {
case ApplyGlaze:
return updateWhen ( donut => donut.id === action.donutId )
, { glaze: action.glaze }
, donuts
)
default:
return donuts
}
}