Advertisement
Help Keep Boards Alive. Support us by going ad free today. See here: https://subscriptions.boards.ie/.
If we do not hit our goal we will be forced to close the site.

Current status: https://keepboardsalive.com/

Annual subs are best for most impact. If you are still undecided on going Ad Free - you can also donate using the Paypal Donate option. All contribution helps. Thank you.
https://www.boards.ie/group/1878-subscribers-forum

Private Group for paid up members of Boards.ie. Join the club.

haskell - processing list of pairs..

  • 23-10-2009 02:49PM
    #1
    Registered Users, Registered Users 2 Posts: 2,238 ✭✭✭


    Hi There,

    I'm having some hassle in Haskell atm. Basically i'm trying to get a list of pairs and sum the first elements of each pair and the second elements of each pair.
    eg. sumPairs [(1,2),(2,3),(4,5),(6,7)]
    => (13,17)

    I am able to sum all of the pairs and return a list of the sums of each pair but thats it.

    When I try this I get all kinds of type errors:
    addPair (a,b) (c,d) = ((a+c),(b,d))
    addPairs (a:b:as) = map addPair a b
    
    In the above code i'm taking the first two pairs from the list as and maping them to addPair. How to I define addPair to take two pairs and return one pair?

    I'm competely lost on this..any help appreciated.

    UPDATE:

    I've just gotten addPair to work on its own with two pairs supplied as arguments. When I try and map that function to a list of pairs i'm getting an error
    Type error in application.:
    Expression: map addPair a b
    Term: map
    Type: (e-> f) -> [e] -> [f]
    Does not match: a->b->c->d

    Here's the code:
    addPair :: (Integer,Integer) -> (Integer,Integer) -> (Integer,Integer)
    addPair (a,b) (c,d) = (a+c,b+d)
    addPairs (a:b:as) = map addPair a b
    

    What does the error mean anyway?

    Thanks..


Comments

  • Registered Users, Registered Users 2 Posts: 1,919 ✭✭✭ronivek


    So the first problem is that you're using map incorrectly; it's giving you the type for map which is (e-> f) -> [e] -> [f].

    This is telling you map expects two arguments; the first a function mapping some e to some f, the second a list of e and the result is a list of f.

    The second problem is that map isn't really what you want in this instance; map is simply mapping the elements of some list of length n to some other list of length n. What you're looking to do is to effectively accumulate the values of some list of length n into a single element.

    I would suggest taking a look at foldr and/or foldl; go here http://www.haskell.org/onlinereport/standard-prelude.html; and do a search for foldl and foldr to have a look at the definitions and see if that gives you any ideas.


  • Registered Users, Registered Users 2 Posts: 2,238 ✭✭✭techguy


    Here's what I got to work.
    addPairs [] = (0,0)
    addPairs ((a,b) :as) =
    	let(x,y) = addPairs as in
    		(a+x,b+y)
    
    

    It's the first time using let,in. Hadn't thought of it before. Thanks for your help.


  • Registered Users, Registered Users 2 Posts: 1,919 ✭✭✭ronivek


    Here's my solution using foldl just for future reference;
    addPairs :: (Num a, Num b) => [(a, b)] -> (a, b)
    addPairs ps = foldl (\(x, y) (acc_x, acc_y) -> (x + acc_x, y + acc_y)) (0, 0) ps
    

    Or in an alternative form;
    addPairs2 :: (Num a, Num b) => [(a, b)] -> (a, b)
    addPairs2 ps = foldl addPairAccum (0, 0) ps
    
    addPairAccum :: (Num a, Num b) => (a, b) -> (a, b) -> (a, b)
    addPairAccum (x, y) (acc_x, acc_y) = (x + acc_x, y + acc_y)
    


Advertisement