문제

도트의 차이점은 무엇입니까? (.) 그리고 달러 사인 ($)?

내가 이해하는 것처럼, 그들은 괄호를 사용할 필요가 없기 때문에 구문 설탕입니다.

도움이 되었습니까?

해결책

그만큼 $ 연산자는 괄호를 피하기위한 것입니다. 이전에 나타나는 것은 이전에 오는 것보다 우선합니다.

예를 들어, 읽는 줄이 있다고 가정 해 봅시다.

putStrLn (show (1 + 1))

그 괄호를 제거하려면 다음 줄 중 하나도 같은 일을합니다.

putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1

의 주요 목적 . 연산자는 괄호를 피하는 것이 아니라 체인 기능을 사용해야합니다. 왼쪽에 나타나는 내용의 입력에 오른쪽에 나타나는 모든 것의 출력을 묶을 수 있습니다. 이것은 일반적으로 괄호가 줄어들지 만 다르게 작동합니다.

같은 예로 돌아가는 것 :

putStrLn (show (1 + 1))
  1. (1 + 1) 입력이 없으므로 . 운영자.
  2. show 취할 수 있습니다 Int 그리고 반환 a String.
  3. putStrLn a String 그리고 반환 IO ().

당신은 체인 할 수 있습니다 show 에게 putStrLn 이와 같이:

(putStrLn . show) (1 + 1)

그것이 당신의 취향에 대해 너무 많은 괄호라면 $ 운영자:

putStrLn . show $ 1 + 1

다른 팁

그들은 다른 유형과 다른 정의를 가지고 있습니다.

infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)

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

($) 정상 기능 응용 프로그램을 대체하기위한 것이지만 괄호를 피하는 데 도움이되는 다른 우선 순위입니다. (.) 새로운 기능을 만들기 위해 두 가지 기능을 함께 작성하는 것입니다.

어떤 경우에는 상호 교환 가능하지만 일반적으로 사실은 아닙니다. 그들이있는 전형적인 예는 다음과 같습니다.

f $ g $ h $ x

==>

f . g . h $ x

다시 말해서 $S, 마지막을 제외한 모든 것은 .

또한 주목하십시오 ($) ~이다 기능 유형에 특화된 ID 기능. ID 기능은 다음과 같습니다.

id :: a -> a
id x = x

하는 동안 ($) 이렇게 보인다 :

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

유형 서명에 의도적으로 추가 괄호를 추가했습니다.

사용 ($) 일반적으로 괄호를 추가하여 제거 할 수 있습니다 (연산자가 섹션에서 사용되지 않는 한). 예 : f $ g x becomes f (g x).

사용 (.) 교체하기가 약간 더 어렵습니다. 일반적으로 람다 또는 명시 적 기능 매개 변수의 도입이 필요합니다. 예를 들어:

f = g . h

becomes

f x = (g . h) x

becomes

f x = g (h x)

도움이 되었기를 바랍니다!

($) 평가 순서를 제어하기 위해 괄호를 추가하지 않고 기능을 함께 연결할 수 있습니다.

Prelude> head (tail "asdf")
's'

Prelude> head $ tail "asdf"
's'

작용 연산자 (.) 인수를 지정하지 않고 새로운 기능을 만듭니다.

Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'

Prelude> let second = head . tail
Prelude> second "asdf"
's'

위의 예는 틀림없이 예시 적이지만 실제로 구성 사용의 편의성을 보여주지는 않습니다. 다음은 또 다른 비유입니다.

Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"

우리가 세 번째로 한 번만 사용하면 람다를 사용하여 이름 지정을 피할 수 있습니다.

Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"

마지막으로, 구성은 람다를 피할 수 있습니다.

Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"

짧고 달콤한 버전 :

  • ($) 오른쪽 인수 인 값에 대한 왼쪽 인수 인 함수를 호출합니다.
  • (.) 오른쪽 인수 인 함수에 대한 왼쪽 인수 기능을 작성합니다.

유용하고 매우 간단한 설명에서 알아내는 데 시간이 걸린 응용 프로그램 중 하나입니다. Haskell을 배우십시오: 부터:

f $ x = f x

디픽스 연산자가 포함 된 표현식의 오른쪽을 괄호로 만드는 것은 접두사 함수로 변환합니다. ($ 3) (4+) 유사합니다 (++", world") "hello".

왜 누군가 이것을할까요? 예를 들어 함수 목록의 경우. 둘 다:

map (++", world") ["hello","goodbye"]`

그리고:

map ($ 3) [(4+),(3*)]

보다 짧습니다 map (\x -> x ++ ", world") ... 또는 map (\f -> f 3) .... 분명히, 후자의 변형은 대부분의 사람들에게 더 읽기 쉬울 것입니다.

... 또는 당신은 피할 수 있습니다 . 그리고 $ 사용하여 구성 파이프 라인:

third xs = xs |> tail |> tail |> head

헬퍼 기능을 추가 한 후입니다.

(|>) x y = y x

모든 것에 대해 더 많이 배우는 좋은 방법 (모든 기능)은 모든 것이 기능이라는 것을 기억하는 것입니다! 그 일반적인 만트라는 도움이되지만 운영자와 같은 특정 경우에는이 작은 트릭을 기억하는 데 도움이됩니다.

:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

그리고

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

사용해야합니다 :t 자유롭게 운영자를 감싸십시오 ()!

내 규칙은 간단합니다 (나도 초보자) :

  • 사용하지 마세요 . 매개 변수를 전달하려면 (함수 호출).
  • 사용하지 마세요 $ 아직 매개 변수가없는 경우 (함수 구성)

그건

show $ head [1, 2]

그러나 절대 :

show . head [1, 2]

Haskell : 차이 . (도트) 및 $ (달러 표시)

도트의 차이점은 무엇입니까? (.) 그리고 달러 사인 ($)?. 내가 이해하는 것처럼, 그들은 괄호를 사용할 필요가 없기 때문에 구문 설탕입니다.

그들은 ~ 아니다 괄호를 사용할 필요가없는 구문 설탕 - 기능입니다.

구성하다, (.), 그리고 그것을 사용하는시기.

(.) 작곡 함수입니다. 그래서

result = (f . g) x

인수의 결과를 전달하는 함수를 구축하는 것과 동일합니다. gf.

h = \x -> f (g x)
result = h x

사용 (.) 작성하려는 기능으로 전달할 수있는 인수가 없으면.

올바른 연관 적용, ($), 그리고 그것을 사용하는시기

($) 결합 우선 순위가 낮은 올바른 연관 적용 기능입니다. 따라서 먼저 오른쪽의 물건을 계산합니다. 따라서,

result = f $ g x

이와 동일합니다. 절차 적으로 (Haskell이 게으르게 평가되기 때문에 중요하면 평가를 시작합니다. f 첫 번째):

h = f
g_x = g x
result = h g_x

또는 더 간결하게 :

result = f (g x)

사용 ($) 이전 기능을 결과에 적용하기 전에 평가할 모든 변수가있는 경우.

각 함수의 소스를 읽음으로써 이것을 볼 수 있습니다.

소스를 읽으십시오

여기에 있습니다 원천 ~을 위한 (.):

-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

그리고 여기에 있습니다 원천 ~을 위한 ($):

-- | Application operator.  This operator is redundant, since ordinary
-- application @(f x)@ means the same as @(f '$' x)@. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- >     f $ g $ h x  =  f (g (h x))
--
-- It is also useful in higher-order situations, such as @'map' ('$' 0) xs@,
-- or @'Data.List.zipWith' ('$') fs xs@.
{-# INLINE ($) #-}
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

결론

기능을 즉시 평가할 필요가 없을 때 구성을 사용하십시오. 어쩌면 구성에서 다른 함수로 결과가 발생하는 함수를 전달하고 싶을 수도 있습니다.

전체 평가를 위해 모든 인수를 제공 할 때 응용 프로그램을 사용하십시오.

그래서 우리의 예를 위해서는 의미 적으로 바람직 할 것입니다.

f $ g x

우리가 가지고있을 때 x (또는 오히려, g의 주장) 및 수행 :

f . g

우리가하지 않을 때.

어디에서 사용할 것인지에 대한 짧은 예라고 생각합니다. . 그리고 아닙니다 $ 사물을 명확히하는 데 도움이 될 것입니다.

double x = x * 2
triple x = x * 3
times6 = double . triple

:i times6
times6 :: Num c => c -> c

주목하십시오 times6 기능 구성에서 생성 된 함수입니다.

다른 모든 대답은 꽤 좋습니다. 그러나 GHC가 $를 취급하는 방법에 대한 중요한 유용성 세부 사항이 있습니다. GHC 유형 검사기는 높은 순위/ 정량화 된 유형으로 인스턴티 리온을 허용합니다. 유형을 보면 $ id 예를 들어, 논쟁 자체가 다형성 기능인 함수를 취할 것입니다. 그와 같은 작은 것들은 동등한 화가 연산자와 동일한 유연성을 제공하지 않습니다. (이것은 실제로 $! 같은 치료를받을 자격이 있는지 궁금해합니다)

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