4

Part of some computation I am doing in Haskell results in a list of functions that map Float to Float. I'd like to apply a single argument to all these functions, like so:

-- x :: Float
-- functions :: [Float -> Float]
map (\f -> f x) functions

Is there a way to do this without making use of a throw-away lambda function? I've searched Hoogle for what I think the signature should be ([a -> b] -> a -> [b]) with no luck.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Daniel Buckmaster
  • 7,108
  • 6
  • 39
  • 57
  • see http://stackoverflow.com/questions/11709350 – Matvey Aksenov Oct 30 '12 at 08:13
  • 1
    Just a heads-up, there is a program called `pointfree` (`cabal install pointfree`) that can do these sort of reductions automagically. e.g. `map (\f -> f x) fs` becomes `map ($ x) fs` as desired. – huon Oct 30 '12 at 09:35

2 Answers2

9

You can use the $ operator, which is just function application:

map ($ x) functions

(This presupposes that x is in scope for the expression.)

Hoogle can only find functions, not arbitrary expressions. Since you're using map, you wanted to search for a function like (a -> b) -> a -> b rather than anything involving lists. Given a normal function, passing it to map makes it act on lists.

Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
  • Yeah, I think I was getting a bit confused with the signature. Thanks! I understand how `$` defines precedence, but how does it work in this case? – Daniel Buckmaster Oct 30 '12 at 08:12
  • 2
    The operator is defined very simply: `f $ x = f x`. So it really is just function application, as an operator. When you partially apply it, you get something equivalent to `\ f -> f $ x`; using the above definition, this works out to `\ f -> f x`, which is exactly what you had. – Tikhon Jelvis Oct 30 '12 at 08:14
  • As I understand it, `map f xs` sort of does `f x` for each `x` in `xs`. So it looks to me like `$ f x`, hence my confusion! – Daniel Buckmaster Oct 30 '12 at 08:19
  • Your understanding of `map` is correct. However, you may be a little confused by operator sections. In Haskell, you can partially apply operators by passing in an argument to *either* side. So you could write `(1 +)`, which is the function `\ x -> 1 + x`, but you could also write `(+ 1)` which is the function `\ x -> x + 1`. In this case, I'm doing exactly that except with the `$` operator. – Tikhon Jelvis Oct 30 '12 at 08:24
  • Sorry, in my comment above I meant it looks like `$ x f`. Which passes the argument `x` from the left? – Daniel Buckmaster Oct 30 '12 at 08:29
  • @DanielBuckmaster `$ f x` is invalid Haskell syntax. `($ f x)` is invalid Haskell expression. `($) f x` means `(f $) x` means `($ x) f` means `f x`. You get operator section by enclosing partial operator application expression in *parentheses*. – Will Ness Oct 30 '12 at 08:32
  • Yeah, that's what I was trying to get at: since `$` is an operator, `($ x)` passes `x` in from the *right* rather than the left. Just like `(* 2)` passes `2` in from the right, `($ x)` does with `x`. I hope I've clarified this a bit rather than making you more confused :). – Tikhon Jelvis Oct 30 '12 at 08:32
  • @DanielBuckmaster In `(f $) x`, `f` is on the left of `$` so `x` goes on its right. In `($ x) f`, `x` is on the right of `$` so `f` goes on its left. In the end, both end up as `f $ x`. – Will Ness Oct 30 '12 at 08:39
6

functions <*> pure x should do it. Import Control.Applicative module first.

Also consider this:

Prelude Control.Applicative> [(1+),(2+)] <*> pure 4
[5,6]
Prelude Control.Applicative> [(1+),(2+)] <*> [4]
[5,6]
Prelude Control.Applicative> [(1+),(2+)] <*> [4,5]
[5,6,6,7]
Prelude Control.Applicative> [(+)] <*> [1,2] <*> [4,5]
[5,6,6,7]
Prelude Control.Applicative> (+) <$> [1,2] <*> [4,5]
[5,6,6,7]
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> ZipList [4,5]
[5,7]
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> pure 4
[5,6]

<$> is just a synonym for fmap. <*> applies what's "carried" in the applicative functor on the left, to what's on the right, according to a certain semantics. For naked lists, the semantics is the same as list monad - make all possible combinations - apply each function from the left to each object on the right, and pure x = [x]. For lists tagged (i.e. newtyped) as ZipLists, the semantics is "zippery" application - i.e. one-on-one, and pure x = ZipList $ repeat x.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • 2
    These functions are actually defined for applicative functors rather than monads. Applicatives are more general--all monads are also applicatives, but not vice versa. – Tikhon Jelvis Oct 30 '12 at 08:23
  • Haha, I'm still at the stage where I assume weird things in Haskell are monads! I will do some research - thanks for the tip. – Daniel Buckmaster Oct 30 '12 at 08:29