Điều này phải làm với phân tích cú pháp. Trong Haskell, bạn có thể viết (op arg)
trong đó op
là một toán tử kết hợp. Điều này không giống như ((op) arg)
. Và bạn cũng có thể viết (arg op)
! Ví dụ:
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
Đó là, (+ 4)
là hàm \x -> x + 4
và (4 +)
là hàm \y -> 4 + y
. Trong trường hợp bổ sung, đây là những chức năng bình đẳng, nhưng điều đó không thực sự quan trọng ngay bây giờ.
Bây giờ chúng ta hãy thử các mẹo cùng trên $
:
Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
Bây giờ sự ngạc nhiên cho đến nay, chúng tôi đã nhận \f -> f $ [1,2,3,4]
. Chúng tôi cũng có thể viết
Prelude> :t (length $)
(length $) :: [a] -> Int
để nhận hàm \l -> length $ l
. Nhưng làm thế nào về điều này:
Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
Điều này thật kỳ lạ nhưng có ý nghĩa! Chúng tôi đã nhận được \f -> f $ length
, tức là, một chức năng dự kiến sẽ nhận được chức năng f
loại ([a] -> Int) -> b)
sẽ được áp dụng cho length
. Có khả năng thứ tư:
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] $)
Mọi thứ phải vì [1,2,3,4]
không phải là chức năng. Nếu chúng tôi viết $
trong ngoặc đơn thì sao? Sau đó, ý nghĩa đặc biệt của nó như là một nhà điều hành ghi biến mất:
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] ($))
Vì vậy, để trả lời câu hỏi của bạn: $ [1,2,3,4]
được phân tách như \f -> f $ [1,2,3,4]
nên nó làm cho cảm giác hoàn hảo để áp dụng nó vào length
. Tuy nhiên ($) [1, 2, 3, 4]
không có ý nghĩa nhiều bởi vì ($)
không được xem như là một toán tử infix.
Nhân tiện, $
không "không làm gì cả", để nói. Nó được sử dụng chủ yếu cho đầu vào dễ đọc hơn vì nó có ưu tiên thấp và vì vậy chúng tôi có thể viết f $ g $ h $ x
thay vì f (g (h x))
.
Đây không phải là về '($)', mà là về các toán tử. – phg
'$' * không * trì hoãn việc đánh giá hàm này sang trái. Bạn có thể nhầm lẫn nó với '$!', Điều này buộc một phần đánh giá đối số về bên phải của nó trước khi đưa nó vào hàm ở bên trái của nó. – dave4420
Đây là cú pháp "phần" tại nơi làm việc. http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-300003.5 –