Questo ha a che fare con l'analisi. In Haskell puoi scrivere (op arg)
dove op
è un operatore infisso. Questo non è lo stesso di ((op) arg)
. E puoi anche scrivere (arg op)
! Ad esempio:
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
Cioè, (+ 4)
è la funzione \x -> x + 4
e (4 +)
è la funzione \y -> 4 + y
. Nel caso di aggiunta, queste sono funzioni uguali, ma al momento non è molto importante.
Ora proviamo lo stesso trucco su $
:
Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
Ora sorpresa finora, abbiamo ottenuto \f -> f $ [1,2,3,4]
. Possiamo anche scrivere
Prelude> :t (length $)
(length $) :: [a] -> Int
per ottenere la funzione \l -> length $ l
. Ma che dire di questo:
Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
Questo è strano, ma ha senso! Abbiamo ottenuto \f -> f $ length
, ad es., un funzionale che si aspetta di ottenere una funzione f
di tipo ([a] -> Int) -> b)
che verrà applicata a length
. C'è una quarta possibilità:
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] $)
Tutto è come dovrebbe essere perché [1,2,3,4]
non è una funzione. Cosa succede se scriviamo $
tra parentesi? Poi il suo significato speciale come un operatore infisso scompare:
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] ($))
Quindi, per rispondere alla tua domanda: $ [1,2,3,4]
viene analizzato come \f -> f $ [1,2,3,4]
quindi ha senso perfetto per applicarlo al length
. Tuttavia, ($) [1, 2, 3, 4]
non ha molto senso perché ($)
non è visto come un operatore infisso.
A proposito, lo "$
" non fa nulla ", per così dire. Viene utilizzato principalmente per l'input più leggibile perché ha una precedenza bassa e quindi è possibile scrivere f $ g $ h $ x
anziché f (g (h x))
.
Non si tratta di '($)', ma di sezioni dell'operatore. – phg
'$' * non * ritarda la valutazione della funzione a sinistra. Potresti confonderla con '$!', Che forza la valutazione parziale dell'argomento alla sua destra prima di alimentarla alla funzione alla sua sinistra. – dave4420
Questa è la sintassi della "sezione" al lavoro. http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-300003.5 –