Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rewriting an uncurried function haskell

I've been learning about uncurrying and applying $ in functions in haskell but I'm still having issues converting an uncurried function to something less mysterious.

The function I'm given is

apple = map $ uncurry $ flip ($)

and I realize that this takes a list of tuples and applies to corresponding function in the tuple to the variable inside. So I'm trying to rewrite it as

apple ls = foldr function _ ls
    where function (a,b) c = (uncurry b) (a,c)

I get the error for _ as a parse error and I have no idea which starting point to use. I need to make this polymorphic and I'm realizing that this most likely will not be the way to make it less mysterious. Any ideas? They'd be greatly appreciated

like image 215
user2913600 Avatar asked Oct 24 '13 00:10

user2913600


2 Answers

Apple has the type

apple :: [(a, a->b)] -> [b]

We could rewrite it as

apple ls = map (\(a, f) -> f a) ls

So writing this with foldr is very doable,

apple ls = foldr (\(a, f) rest -> f a : rest) [] ls

Or, we can rewrite this to pointfree

apple = foldr ( (:) . (uncurry . flip $ ($)) ) []

The reason for the parse error is that _ is the special syntax for "variables I don't care about". This let's you write things like

 foo _ _ _ _ a = a

And not get an error about repeated variables. Basically we just filled in _ with the starting empty list and fixed function so that it appends to c rather than trying to apply it to a.

If I wanted to write this in the clearest way possible, then the original

apple = map . uncurry . flip $ ($)

Is quite nice.

like image 122
Daniel Gratzer Avatar answered Nov 07 '22 05:11

Daniel Gratzer


The key for understanding is removing complexity.

Thus I would suggest you deal with a single tuple first. Write the following function:

 tapp :: (a, a ->b) -> b

in terms of ($) and flip and uncurry. (To make it even easier, you could first do it for a tuple (a -> b, a) first).

Next, make clear to yourself how map works: If you have a function f :: (a -> b), then map f will be a function [a] -> [b]. Hence map tapp does what you want.

You can now replace tapp in map (tapp) by it's definition (this are the benefits of referential transparency). And this should take you back to your original expression. More or less so, because, for example:

f $ g h

can be written

f (g h)

or

(f . g) h
like image 41
Ingo Avatar answered Nov 07 '22 05:11

Ingo