Das hat mit dem Parsen zu tun. In Haskell können Sie (op arg)
schreiben, wobei op
ein Infix-Operator ist. Dies ist nicht dasselbe wie ((op) arg)
. Und Sie können auch (arg op)
schreiben! Zum Beispiel:
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
Das heißt, (+ 4)
ist die Funktion \x -> x + 4
und (4 +)
ist die Funktion \y -> 4 + y
. Im Fall von Addition sind das gleiche Funktionen, aber das ist im Moment nicht wirklich wichtig.
lassen Sie uns nun den gleichen Trick auf $
versuchen:
Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
Jetzt Überraschung so weit, wir haben \f -> f $ [1,2,3,4]
. Wir können auch schreiben
Prelude> :t (length $)
(length $) :: [a] -> Int
die Funktion \l -> length $ l
zu erhalten. Aber wie wäre es damit:
Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
Das ist seltsam, aber es macht Sinn! Wir haben \f -> f $ length
, d.h., eine funktionale, die eine Funktion f
des Typs ([a] -> Int) -> b)
erwartet, die auf length
angewendet wird. Es gibt eine vierte Möglichkeit:
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] $)
Alles ist, wie es sein sollte, weil [1,2,3,4]
keine Funktion ist. Was ist, wenn wir $
in Klammern schreiben? Dann seine besondere Bedeutung als Infixoperator verschwindet:
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] ($))
Also, Ihre Frage zu beantworten: $ [1,2,3,4]
analysiert wird als \f -> f $ [1,2,3,4]
so macht es durchaus Sinn, es zu length
anzuwenden. ($) [1, 2, 3, 4]
macht jedoch keinen Sinn, da ($)
nicht als Infix-Operator betrachtet wird.
Übrigens, $
tut "nichts", sozusagen. Es wird hauptsächlich für lesbarere Eingaben verwendet, da es eine niedrige Priorität hat und wir daher f $ g $ h $ x
anstelle von f (g (h x))
schreiben können.
Hier geht es nicht um '($)', sondern um Operatorabschnitte. – phg
'$' * verzögert die Auswertung der Funktion nicht. Sie können es mit '$!' Verwechseln, was eine Teilbewertung des Arguments nach rechts bewirkt, bevor es der Funktion zu seiner Linken zugeführt wird. – dave4420
Dies ist "Abschnitt" -Syntax bei der Arbeit. http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-300003.5 –