将函数应用于列表中的每个元素到另一个列表中的每个元素

时间:2019-12-05 16:26:24

标签: haskell

我想要一种更优雅的方式来编写以下两个函数,理想情况下是一个:

applyOperatorBetweenVariableLists:: [Variable] -> String -> [Variable] -> [Variable]
applyOperatorBetweenVariableLists firstList operator secondList = concat $ map (test firstList operator) secondList

test:: [Variable] -> String -> Variable -> [Variable]
test firstVariables operator secondVariable = concat $ map (applyOperatorBetweenVariables secondVariable operator) firstVariables

applyOperatorBetweenVariables的声明是:

applyOperatorBetweenVariables:: Variable -> String -> Variable -> [Variable]

我很确定必须有一个Prelude函数可以做到这一点,或者是一种非常优雅的编写方式。

1 个答案:

答案 0 :(得分:1)

可以使用do块来简洁地完成此操作:

applyOperatorBetweenVariableLists firstList operator secondList = do
  secondVariable <- secondList
  firstVariable <- firstList
  applyOperatorBetweenVariables secondVariable operator firstVariable

如果您想更加简洁,可以将参数applyOperatorBetweenVariableListsapplyOperatorBetweenVariables重新排序,然后使用liftJoin2bind2来实现(就像我下面的最后一句话一样,但用liftA2代替了。


我最初的回答是错误的,因为它留下了一层嵌套(即应该做额外的concatjoin):

这几乎是{em> liftA2,但您的论据却很奇怪。在此方面,您将如何实现所写内容:

import Control.Applicative (liftA2)
applyOperatorBetweenVariableLists firstList operator secondList = liftA2 (flip applyOperatorBetweenVariables operator) secondList firstList

根据该定义,应该清楚如何通过重新排序applyOperatorBetweenVariableLists = liftA2 . applyOperatorBetweenVariablesapplyOperatorBetweenVariables的参数来将其更改和简化为const schema = new Schema({ associations: [{ type: mongoose.SchemaTypes.Mixed, ref: doc => doc.modelType }] }); const Product = mongoose.model('Product', schema); const products = await Product.find().populate('associations');