차이점은 무엇입니까? (도트) 및 $ (달러 표시)?
-
06-09-2019 - |
문제
도트의 차이점은 무엇입니까? (.)
그리고 달러 사인 ($)
?
내가 이해하는 것처럼, 그들은 괄호를 사용할 필요가 없기 때문에 구문 설탕입니다.
해결책
그만큼 $
연산자는 괄호를 피하기위한 것입니다. 이전에 나타나는 것은 이전에 오는 것보다 우선합니다.
예를 들어, 읽는 줄이 있다고 가정 해 봅시다.
putStrLn (show (1 + 1))
그 괄호를 제거하려면 다음 줄 중 하나도 같은 일을합니다.
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
의 주요 목적 .
연산자는 괄호를 피하는 것이 아니라 체인 기능을 사용해야합니다. 왼쪽에 나타나는 내용의 입력에 오른쪽에 나타나는 모든 것의 출력을 묶을 수 있습니다. 이것은 일반적으로 괄호가 줄어들지 만 다르게 작동합니다.
같은 예로 돌아가는 것 :
putStrLn (show (1 + 1))
(1 + 1)
입력이 없으므로.
운영자.show
취할 수 있습니다Int
그리고 반환 aString
.putStrLn
aString
그리고 반환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
인수의 결과를 전달하는 함수를 구축하는 것과 동일합니다. g
에 f
.
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
예를 들어, 논쟁 자체가 다형성 기능인 함수를 취할 것입니다. 그와 같은 작은 것들은 동등한 화가 연산자와 동일한 유연성을 제공하지 않습니다. (이것은 실제로 $! 같은 치료를받을 자격이 있는지 궁금해합니다)