Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

haskell - processing list of pairs..

Options
  • 23-10-2009 2:49pm
    #1
    Registered Users Posts: 2,234 ✭✭✭


    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 Posts: 1,916 ✭✭✭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 Posts: 2,234 ✭✭✭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 Posts: 1,916 ✭✭✭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