문제

I know

$ :: (a->b) -> a -> b
f $ x = f x

Intuitively it seems to me, like to say, 1. $ delays the evaluation of the function to its left 2. evaluates whats to its right 3. feeds the result of its left to its right.

And it makes perfect sense to me when,

ghci> length $ [1..5]
5
ghci> ($) length [1..5]
5

What I do not understand is why,

ghci> ($ [1..5]) length
5

Judging from the type of $, isn't that its (first) argument should be a function ?

도움이 되었습니까?

해결책

This has to do with parsing. In Haskell you can write (op arg) where op is an infix operator. This is not the same as ((op) arg). And you can write (arg op) as well! For example:

GHCi, version 7.0.3: http://www.haskell.org/ghc/  :? for help
Prelude> :t (+ 4)
(+ 4) :: Num a => a -> a
Prelude> :t (4 +)
(4 +) :: Num a => a -> a

That is, (+ 4) is the function \x -> x + 4 and (4 +) is the function \y -> 4 + y. In the case of addition these are equal functions, but that is not really important right now.

Now let us try the same trick on $:

Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b

Now surprise so far, we got \f -> f $ [1,2,3,4]. We can also write

Prelude> :t (length $)
(length $) :: [a] -> Int

to get the function \l -> length $ l. But how about this:

Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b

This is strange, but it makes sense! We got \f -> f $ length, i.e., a functional which expects to get a function f of type ([a] -> Int) -> b) that will be applied to length. There is a fourth possibility:

Prelude> :t ([1,2,3,4] $)

<interactive>:1:2:
    Couldn't match expected type `a0 -> b0' with actual type `[t0]'
    In the first argument of `($)', namely `[1, 2, 3, 4]'
    In the expression: ([1, 2, 3, 4] $)

Everything is as it should be because [1,2,3,4] is not a function. What if we write $ in parenthesis? Then its special meaning as an infix operator disappears:

Prelude> :t (($) length)
(($) length) :: [a] -> Int

Prelude> :t (($) [1,2,3,4])
<interactive>:1:6:
    Couldn't match expected type `a0 -> b0' with actual type `[t0]'
    In the first argument of `($)', namely `[1, 2, 3, 4]'
    In the expression: (($) [1, 2, 3, 4])

Prelude> :t (length ($))
<interactive>:1:9:
    Couldn't match expected type `[a0]'
                with actual type `(a1 -> b0) -> a1 -> b0'
    In the first argument of `length', namely `($)'
    In the expression: (length ($))

Prelude> :t ([1,2,3,4] ($))
<interactive>:1:2:
    The function `[1, 2, 3, 4]' is applied to one argument,
    but its type `[t0]' has none
    In the expression: ([1, 2, 3, 4] ($))

So, to answer your question: $ [1,2,3,4] is parsed as \f -> f $ [1,2,3,4] so it makes perfect sense to apply it to length. However ($) [1, 2, 3, 4] does not make much sense because ($) is not seen as an infix operator.

By the way, $ does "not do anything", so to speak. It is mostly used for more readable input because it has low precedence and so we can write f $ g $ h $ x instead of f (g (h x)).

다른 팁

Your question is really about what is called operator sections. With any operator in Haskell (I will use + as an example) you can write something like (+ arg) or (arg +). These are just shorthand syntax for the anonymous functions (\x -> x + arg) and (\x -> arg + x), respectively.

So, the ($ [1..5]) syntax just means (\x -> x $ [1..5]) which is the same as (\x -> x [1..5]) (ie. a function which passes [1..5] to the function passed as its argument).

($ [1..5]) is a section. That's a partially applied operator. It's a shorthand for (\f -> f $ [1..5]).

Sections let you supply one argument to a binary operator and produce a function - a function which is waiting for the remaining argument.

Take a look at http://www.haskell.org/haskellwiki/Section_of_an_infix_operator

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top