How to understand this `` use in Haskell

This happens in a situation where you want to apply a bunch of functions to the same variable, it may look like this:

map (\f->f 4) [odd, even] 

but from LYAH using $ make it very neat

 map ($ 4) [odd, even] 

why does it work. first i print it in ghci as $ 4 odd , it failed, then i type ($ 4) odd , which works fine. then I check the type ($ 4) using :t , which shows ($ 4) :: Num a => (a -> b) -> b , odd is odd :: Integral a => a -> Bool . It seems reasonable, but still not clear to me.

Can anyone explain this clearly, this is another common use of $ , and is there another use of $ .

+2
operators syntax haskell dollar-sign operator-sections
Aug 25 '14 at 15:02
source share
3 answers

Operator anatomy

The application operator $ has the form:

 ($) :: (a -> b) -> a -> b 

This is often seen in situations where you want to avoid a finite pair of brackets:

 func a (b + c) 

equally:

 func a $ b + c 

The magic of this is simply explained in the statement of fixation :

 infixr 0 

This means: everything after $ will be grouped into a single object, as if they were enclosed in parentheses.

Of course, it can also be "nested" as follows:

 func a $ b + other $ c - d 

which means:

 func a (b + other (c - d)) 

Application Operator as a Function

Your case is very interesting and, in my experience, is not used very often.

Let's analyze this:

 map ($ 4) [odd, even] 

We know that type map :

 map :: (a -> b) -> [a] -> [b] 

The behavior, if someone forgot, is as follows: take the first argument (function a to b ) and apply it to all a in the second list of arguments, finally return the resulting list.

You can see ($ 4) as "pass 4 as an argument to something." It means that:

 ($ 4) func 

matches with:

 func $ 4 

So:

 map ($ 4) [odd, even] 

means:

 [($ 4) odd, ($ 4) even] [(odd $ 4), (even $ 4)] [False, True] 

Why (func $) is not required

You can argue that, as you can do (/ 4) and (2 /) , which respectively mean "divide something by 4" and "divide 2 by something", you could do ($ 4) and (func $) and you are right.

Actually:

 (func $) 4 

matches with:

 func $ 4 func 4 

which matches with:

 ($ 4) func 

But the reality is this:

 map (func $) [...] 

would be unnecessary, since the first argument to map always applies to each argument in the list, doing the above:

 map func [...] 
+7
Aug 25 '14 at 15:14
source share
  • $ 4 odd : This will not work because statements must be surrounded by brackets if they are not used in infix form. If you did ($) 4 odd , that would not work, because the order argument is incorrect, you want 4 be the second argument. You could write ($) odd 4 though.

  • ($ 4) odd : This works because it uses operator sections, and here 4 provided as the second argument to $ . It is like (++ "world") "hello " matches "hello " ++ "world" .

  • If you have ($ 4) :: Num a => (a -> b) -> b and odd :: Integral a => a -> Bool , you just need to align the types. Since each Integral a also Num a , we can simply "upgrade" (restrict) Num to Integral for this:

 ($ 4) :: Integral a => (a -> b) -> b odd :: Integral a => a -> Bool 

So a ~ a and b ~ Bool , so you can say that

 ($ 4) :: Integral a => (a -> Bool) -> Bool 

Therefore, applying it to odd , we get

 ($ 4) odd :: Bool 

This is because ($ 4) odd matches odd $ 4 . Looking at the definition of $ :

 f $ x = fx 

We can say that

 odd $ 4 = odd 4 

Which evaluates to False .

+3
Aug 25 '14 at 15:17
source share

Infix operators, such as * , ++ or $ , usually take two arguments, as in

 x ++ y 

When one argument is missing and they are placed between parentheses, they instead form a section:

 (x ++) (++ y) 

These sections are equivalent, respectively,

 \y -> x ++ y \x -> x ++ y 

ie, they mean a function that maps the "missing argument" to the result. For example,

 map ("A"++) ["a","b"] == [ "Aa","Ab" ] map (++"A") ["a","b"] == [ "aA","bA" ] 

The $ operator is not special in this regard. We have

 (f $) ($ x) 

which means

 \x -> f $ x \f -> f $ x 

The first is not very useful, since (f $) is \x -> f $ x , which (this-) is simply equivalent to f (*). Instead, the second is useful.

(*) To be legible, seq can distinguish between undefined and (undefined $) , but this is a slight difference in practice.

+3
Aug 25 '14 at 15:17
source share



All Articles