8

I have a problem with implementing FP (Backus) interpreter in Haskell.

FP functions look like this:

[+,*]:<2,3>

should result with

<+:<2,3>, *:<2,3>> ->
<5,6>

meaning that every function from list on left side should be performed on every every element of a list on a right side.

What I understand is that I need something similar to "map" function, but map applies one function on a list, and I need list of functions on a list of values.

Thank you in advance! :-)

EDIT:

Since I wasn't precise, here is my code that doesn't work:

apply :: [String] -> [Integer] -> [Integer]
apply fs v = [((apply_f f x) | f <- fs | x <- v)]

apply_f :: String -> [Integer] -> [Integer]
apply_f "+" v = [(sum v)]
apply_f "*" v = [(product v)]

I can't figure out why... :-(

EDIT 2:

Sorry, I was too tired from working all day on this. Problem is that I don't need second pipe, just first one:

apply fs v = [ apply_f f v | f <- fs ]

Now, everything works just fine, thank you very much! :-)

1
  • What exactly do you mean with "doesn't work"? Commented Aug 25, 2012 at 18:11

5 Answers 5

18

I believe you are looking for the zipWith function and apply it with the function application operator $.

So, if you have a list of functions funcList and a list of values valueList you would call this with:

zipWith ($) funcList valueList

So, using this would be something like

zipWith ($) [(+ 5),(* 3)] [1,5]

gives you the result [6,15]

To get a sort of cross application you could use

[f a | f <- [(+5), (*3)], a <- [1,5]]

this gives you [6,10,3,15]. Not sure what you mean by the `<, do you want pairs, nested lists or what exactly do you need?

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

3 Comments

No, no not exactly what I had in mind. In FP each function on the left side is applied on EACH value of the list on the right side. So, result of that function you mentioned in FP would be: [+5,*3]:<1,5> -> < <6,11>, <3,15> >
I see... Let me see what I can do for you :)
Sorry for "<>" confusion. That's just how FP represents lists. So, just think of it as normal "[]"
17

It sounds like you want:

import Control.Applicative
apply :: [a -> b] -> [a] -> [b]
apply fs vals = fs <*> vals

Of course this is just the same as the instance of <*> defined for lists.

1 Comment

Or just apply = (<*>) for the third line (making it obvious it's exactly the same)
6

Do you want something like this?

[f x | f <- [(+3),(*2)], x <- [1..2]]

Output:

[4,5,2,4]

EDIT:

So something like this?

[[f x | f <- [(+3),(*2)]] | x <- [1..2]]
[[4,2],[5,4]]

4 Comments

similar, but [ [4,5] , [2,4] ].
+1 I think you hit the correct wanted result at the end there :)
It definitely looks correct, but for some reason it doesn't work... :-( here is my code: apply :: [String] -> [Integer] -> [String] apply fs v = [((apply_f f x) | f <- fs | x <- v)] apply_f :: String -> [Integer] -> [Integer] apply_f "+" v = [(sum v)] apply_f "*" v = [(product v)]
I posted code in original question, since it is not correctly formatted in comment... :-(
0

I can't figure out anything from your explanation, but here is a possible code, which gives the correct answer for your example:

> map (uncurry foldr1) [((+), [2,3]), ((*), [2,3])]
[5,6]

Comments

-1

I don't know if it's actually that you need, but

Prelude> [f 2 3 | f <- [(+), (*)]]
[5,6]

If you need lists of <2,3> pairs, you can use something like

Prelude> [zipWith f [2, 20] [3, 30] | f <- [(+), (*)]]
[[5,50],[6,600]]

Comments

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.