HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

A "map" function that alternates between two mapping functions

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mapfunctionsalternatesfunctiontwobetweenthatmapping

Problem

I am trying to solve following problem in Haskell using recursion:


Define a recursive function funkyMap :: (a -> b) -> (a -> b) -> [a] -> [b] that takes as arguments two functions f and g and a list xs, and applies f to all elements at even positions [0, 2..] in xs and g to all elements at odd positions [1, 3..] in xs.

Example: funkyMap (+10) (+100) [1, 2, 3, 4, 5] = [(+10) 1, (+100) 2, (+10) 3, (+100) 4, (+10) 5].

I came up with following solution:

h1 p q [] = []
h1 p q ((cnt, val) : xs) = (if odd cnt then (q val) else (p val) ) : h1 p q xs

funkyMap f g xs = h1 f g ( zip [0..] xs)


If I try funkyMap (+10) (+100) [1, 2, 3, 4, 5] I get [11,102,13,104,15] which is expected.

Also funkyMap (+100) (+2) [1] gives [101]

and funkyMap (+100) (+2) [] gives []

Please review this solution and let me know your feedback.

Solution

So, like @pigworker has said your code looks functionally good to me, but you don't have to break up your solution into two parts like this or create a data structure you don't need.

You might find a better solution using a different approach (pattern matching):

funkyMap :: (a -> b) -> (a -> b) -> [a] -> [b]
funkyMap p q [] = []
funkyMap p q [x] = [p x]
funkyMap p q (x : y : xs) = p x : q y : funkyMap p q xs


The real benefit of this is you don't have to create any intermediate data structures.

The idea behind this solution is to let pattern matching do the hard work for you. Really you have 3 senarios for your function

  • when there are no elements in the list (where you probably just want to return the empty list)



  • when you have just one element in the list (where you just want to apply p to the element)



  • when you have 2 or more elements in the list (where you apply p and q, then use recursion to evaluate the rest of the list)



Using pattern matching lets you wrap that logic up in a really obvious way

Code Snippets

funkyMap :: (a -> b) -> (a -> b) -> [a] -> [b]
funkyMap p q [] = []
funkyMap p q [x] = [p x]
funkyMap p q (x : y : xs) = p x : q y : funkyMap p q xs

Context

StackExchange Code Review Q#113156, answer score: 6

Revisions (0)

No revisions yet.