your programing

의 차이점은 무엇입니까?

lovepro 2020. 9. 30. 11:12
반응형

의 차이점은 무엇입니까? (점) 및 $ (달러 기호)?


(.)과 달러 기호 의 차이점은 무엇입니까 ($)?

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


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

예를 들어 다음과 같은 줄이 있다고 가정 해 보겠습니다.

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과를 반환 String.
  3. putStrLn를 취할 수 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 :: a -> a
id x = x

반면 ($)다음과 같다 :

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

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

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

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

f = g . h

된다

f x = (g . h) x

된다

f x = g (h x)

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


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

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

Prelude> head $ tail "asdf"
's'

The compose operator (.) creates a new function without specifying the arguments:

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

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

The example above is arguably illustrative, but doesn't really show the convenience of using composition. Here's another analogy:

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

If we only use third once, we can avoid naming it by using a lambda:

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

Finally, composition lets us avoid the lambda:

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

The short and sweet version:

  • ($) calls the function which is its left-hand argument on the value which is its right-hand argument.
  • (.) composes the function which is its left-hand argument on the function which is its right-hand argument.

One application that is useful and took me some time to figure out from the very short description at learn you a haskell: Since:

f $ x = f x

and parenthesizing the right hand side of an expression containing an infix operator converts it to a prefix function, one can write ($ 3) (4+) analogous to (++", world") "hello".

Why would anyone do this? For lists of functions, for example. Both:

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

and:

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

are shorter than map (\x -> x ++ ", world") ... or map (\f -> f 3) .... Obviously, the latter variants would be more readable for most people.


... or you could avoid the . and $ constructions by using pipelining:

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

That's after you've added in the helper function:

(|>) x y = y x

A great way to learn more about anything (any function) is to remember that everything is a function! That general mantra helps, but in specific cases like operators, it helps to remember this little trick:

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

and

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

Just remember to use :t liberally, and wrap your operators in ()!


My rule is simple (I'm beginner too):

  • do not use . if you want to pass the parameter (call the function), and
  • do not use $ if there is no parameter yet (compose a function)

That is

show $ head [1, 2]

but never:

show . head [1, 2]

Haskell: difference between . (dot) and $ (dollar sign)

What is the difference between the dot (.) and the dollar sign ($)?. As I understand it, they are both syntactic sugar for not needing to use parentheses.

They are not syntactic sugar for not needing to use parentheses - they are functions, - infixed, thus we may call them operators.

Compose, (.), and when to use it.

(.) is the compose function. So

result = (f . g) x

is the same as building a function that passes the result of its argument passed to g on to f.

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

Use (.) when you don't have the arguments available to pass to the functions you wish to compose.

Right associative apply, ($), and when to use it

($) is a right-associative apply function with low binding precedence. So it merely calculates the things to the right of it first. Thus,

result = f $ g x

is the same as this, procedurally (which matters since Haskell is evaluated lazily, it will begin to evaluate f first):

h = f
g_x = g x
result = h g_x

or more concisely:

result = f (g x)

Use ($) when you have all the variables to evaluate before you apply the preceding function to the result.

We can see this by reading the source for each function.

Read the Source

Here's the source for (.):

-- | 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)

And here's the source for ($):

-- | 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

Conclusion

Use composition when you do not need to immediately evaluate the function. Maybe you want to pass the function that results from composition to another function.

Use application when you are supplying all arguments for full evaluation.

So for our example, it would be semantically preferable to do

f $ g x

when we have x (or rather, g's arguments), and do:

f . g

when we don't.


I think a short example of where you would use . and not $ would help clarify things.

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

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

Note that times6 is a function that is created from function composition.


All the other answers are pretty good. But there’s an important usability detail about how ghc treats $, that the ghc type checker allows for instatiarion with higher rank/ quantified types. If you look at the type of $ id for example you’ll find it’s gonna take a function whose argument is itself a polymorphic function. Little things like that aren’t given the same flexibility with an equivalent upset operator. (This actually makes me wonder if $! deserves the same treatment or not )

참고URL : https://stackoverflow.com/questions/940382/what-is-the-difference-between-dot-and-dollar-sign

반응형