Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map a function over the arguments of another function in Haskell?

Tags:

haskell

So initially I wrote:

xs <- getAddrInfo (Just hints) (Just addr) (Just port)

then it seemed to me that the function 'Just :: a -> Maybe a' is kind of "mapped" over 'hints', 'addr', and 'port', so I came up with something like this:

map_arg g f a b c = f (g a) (g b) (g c)
xs <- map_arg Just getAddrInfo hints addr port

but GHC expects (g a), (g b) and (g c) to be of the same type, so this doesn't type check.

Is there a way to do this, or more generically, is there a way to map a function over the arguments of another function?

like image 949
Aufheben Avatar asked Dec 20 '22 22:12

Aufheben


2 Answers

A most generic type signature would looks like

map_arg :: (forall b.b -> a b) -> (a b -> a c -> a d -> e) -> b -> c -> d -> e
map_arg g f a b c = f (g a) (g b) (g c)

for your case, if you choose not to put g as a parameter, you can do

map_just f a b c = f (g a) (g b) (g c) where g = Just
xs <- map_just getAddrInfo hints addr port

or you can just give type signature to g only:

map_arg (g :: forall b.b -> a b) f a b c = f (g a) (g b) (g c)

To bypass the polymorphic type signature, remember we have Control.Functor.Pointed so you can use it:

map_arg :: Pointed p => (p a -> p b -> p c -> d) -> a -> b -> c -> d
map_arg f a b c = f (point a) (point b) (point c)

(The implementation of Pointed for Maybe is Just what you want)

To have a generalized version, note that

map1 :: Pointed p => (p a -> b) -> a -> b
map1 f = f . point

map2 :: Pointed p => (p a -> p b -> c) -> a -> b -> c
map2 f = map1 . map1 f

map3 :: Pointed p => (p a -> p b -> p c -> d) -> a -> b -> c -> d
map3 f = map2 . map1 f

See that? you only need map1 and all others is just simple combination!

like image 119
Earth Engine Avatar answered May 18 '23 14:05

Earth Engine


The short answer is no (if you're talking about a generic map_arg that'd work for any number of arguments).

You might be able to achieve this with Oleg-level type magic, but if you're just looking for the ways to improve your code, there's not much to improve here.

like image 28
Roman Cheplyaka Avatar answered May 18 '23 12:05

Roman Cheplyaka