5

I've created a list of partially applied functions in my REPL like so:

listOfPartiallyAppliedFunctions = map (*) [1..100]

I would then like to create the list of results from completing the function application, which I can easily do by providing a lambda to the map function like so:

let results = map (\x -> x 4) listOfPartiallyAppliedFunctions

Which basically means map the function x applied to 4 over the list of partially applied functions, where x is each partially applied function from the list.

However, I thought it would then follow that I could write:

let results = map (4) listOfPartiallyAppliedFunctions

As there shouldn't be a need to provide a lambda to the map function as it should know to apply 4 to the partially applied functions contained in the listOfPartiallyAppliedFunctions.

However, I am getting this error:

• Non type-variable argument in the constraint: Num ((a -> a) -> b)
  (Use FlexibleContexts to permit this)
• When checking the inferred type
    it :: forall a b. (Num a, Num ((a -> a) -> b), Enum a) => [b]

Can someone help me parse this error? I thought 4 was an instance of type constructor Num?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Thomas Cook
  • 4,371
  • 2
  • 25
  • 42

2 Answers2

9

However, I thought it would then follow that I could write:

let results = map (4) listOfPartiallyAppliedFunctions

No, if you would have performed \x -> 4 x, you could replace it with 4. But since 4 means it is a Num instance, and you likely did not make a function a -> b an instance of Num, the compiler can not solve this. The compiler thus says that it does not find a way to convert the number 4 into a function, and definitely not a function that takes as input a function Num a => a -> a, and then converts this to a b.

You can however write the above as just:

let results = map ($ 4) listOfPartiallyAppliedFunctions

Here we thus perform a sectioning of an infix operator [Haskell-wiki] on the ($) :: (a -> b) -> a -> b function.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 1
    Fantastic answer as always Willem - appreciate it! – Thomas Cook Jul 09 '19 at 14:58
  • Ah, this is the infix function application operator? I have seen it all over the place but never understood it, so this is like saying "Apply the function (that is the current element in my list of partially applied functions that I'm mapping over) to the value 4? – Thomas Cook Jul 09 '19 at 14:59
  • @ThomasCook: the infix operator sectioning, specifies that `($ 4)` is equivalent to `\x -> ($) x 4`, since `($)` is implemented as `($) f x = f x`, it is thus equivalent to `\x -> x 4` – Willem Van Onsem Jul 09 '19 at 15:48
8

Three "laws" of operator sections are

(a `op` b)  =  (a `op`) b  =  (`op` b) a  =  op a b

(the missing argument goes into the free slot near the operator),

or with $,

a b  =  (a $ b)  =  (a $) b  =  ($ b) a  =  ($) a b

Thus

(\ x -> x 4) = (\ x -> x $ 4) = (\ x -> ($ 4) x)

and that, by eta-reduction, is

($ 4) 
Will Ness
  • 70,110
  • 9
  • 98
  • 181