1

I'd like a more elegant way to write the following two functions, ideally in one :

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

The declaration of applyOperatorBetweenVariables is :

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

I'm quite sure there must be a Prelude Function that does exactly this, or a very elegant way to write it.

0

1 Answer 1

1

This can be done concisely with a do block:

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

If you wanted to be even more concise, you could reorder the arguments to both applyOperatorBetweenVariableLists and applyOperatorBetweenVariables, and then use either liftJoin2 or bind2 to implement it (like my final sentence below but with it in place of liftA2).


My original answer was wrong, as it left a layer of nesting (i.e., should have done an extra concat or join):

That's almost just liftA2, but your arguments are in a weird order. Here's how you'd implement what you wrote in terms of that:

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

From that definition, it should be clear how you could change and simplify that to applyOperatorBetweenVariableLists = liftA2 . applyOperatorBetweenVariables just by reordering the arguments to it and to applyOperatorBetweenVariables.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks. I had noticed it missed a concat.
There is an Applicative solution, namely flip applyOperator operator <$> secondList <*> firstList. If you use ApplicativeDo, that might be what the do block desugars to.
@chepner Doesn't that have the same problem as my original wrong answer, in that it will create an extra layer of nesting?
Maybe I'm misinterpreting what the output should be (especially since my suggestion is the same as liftA2, just spelled differently).
But isn't your do block also the same, especially if ApplicativeDo is in use? The extra layer of nesting would come, I think, from using test, which your updated solution ignores.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.