Jaka jest różnica między. (kropka) i $ (znak dolara)?

Jaka jest różnica między kropką (.) a znakiem dolara ($)?

Jak rozumiem, oba są cukrem składniowym, ponieważ nie muszą używać nawiasów.

Author: Matthias Braun, 2009-06-02

13 answers

Operator $ służy do unikania nawiasów. Wszystko, co pojawi się po nim, będzie miało pierwszeństwo przed wszystkim, co nastąpi wcześniej.

Na przykład, załóżmy, że masz linię, która brzmi:

putStrLn (show (1 + 1))

Jeśli chcesz pozbyć się tych nawiasów, każda z następujących linii również zrobi to samo:

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

Głównym celem operatora . nie jest unikanie nawiasów, ale funkcja łańcuchowa. Pozwala związać wyjście tego, co pojawia się na prawo do wejścia tego, co pojawia się po lewej stronie. Zwykle powoduje to również mniejszą liczbę nawiasów, ale działa inaczej.

Wracając do tego samego przykładu:

putStrLn (show (1 + 1))
  1. (1 + 1) nie posiada danych wejściowych i dlatego nie może być używany z operatorem ..
  2. show może wziąć Int i zwrócić String.
  3. putStrLn może wziąć String i zwrócić IO ().

Możesz połączyć show z putStrLn w następujący sposób:

(putStrLn . show) (1 + 1)

If that ' s too many nawiasy dla Twoich upodobań, pozbądź się ich za pomocą operatora $:

putStrLn . show $ 1 + 1
 1267
Author: Michael Steele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-04 20:50:44

Mają różne typy i różne definicje:

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

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

($) jest przeznaczony do zastąpienia normalnej aplikacji funkcji, ale w innym pierwszeństwie, aby uniknąć nawiasów. (.) jest do komponowania dwóch funkcji razem, aby utworzyć nową funkcję.

W niektórych przypadkach są one wymienne, ale nie jest to prawdą w ogóle. Typowy przykład, gdzie są to:
f $ g $ h $ x

==>

f . g . h $ x

Innymi słowy w łańcuchu $ s, wszystkie poza ostatnim mogą być zastąpione przez .

 193
Author: GS - Apologise to Monica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-02 16:42:17

Należy również zauważyć, że ($) jest funkcją tożsamościową wyspecjalizowaną w typach funkcji . Funkcja tożsamościowa wygląda następująco:

id :: a -> a
id x = x

While ($) wygląda tak:

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

Zauważ, że celowo dodałem dodatkowe nawiasy w podpisie typu.

Użycie ($) można zazwyczaj wyeliminować poprzez dodanie nawiasu (chyba że operator jest użyty w sekcji). Np.: f $ g x staje się f (g x).

Zastosowania (.) są często nieco trudniejsze do zastąpienia; są zwykle wymaga lambda lub wprowadzenia jawnego parametru funkcji. Na przykład:

f = g . h

Staje się

f x = (g . h) x

Staje się

f x = g (h x)

Mam nadzieję, że to pomoże!

 126
Author: Martijn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 12:34:03

($) pozwala na łączenie funkcji ze sobą bez dodawania nawiasów do sterującej kolejności ewaluacji:

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

Prelude> head $ tail "asdf"
's'

Operator compose (.) tworzy nową funkcję bez podawania argumentów:

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

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

Powyższy przykład jest prawdopodobnie ilustracyjny, ale tak naprawdę nie pokazuje wygody korzystania z kompozycji. Oto kolejna analogia:

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

Jeśli użyjemy trzeciego tylko raz, możemy uniknąć nazywania go za pomocą lambda:

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

Wreszcie kompozycja pozwala nam unikaj lambdy:

Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
 79
Author: softmechanics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 12:26:47

Wersja krótka i słodka:

  • ($) wywołuje funkcję, która jest jej lewym argumentem na wartości, która jest jej prawym argumentem.
  • (.) komponuje funkcję, która jest jej lewym argumentem, na funkcję, która jest jej prawym argumentem.
 60
Author: ellisbben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 12:21:07

Jedna aplikacja, która jest przydatna i zajęło mi trochę czasu, aby dowiedzieć się z bardzo krótkiego opisu w learn you a haskell : od:

f $ x = f x

I nawias po prawej stronie wyrażenia zawierającego operator infiksu przekształca go w funkcję prefiksu, można zapisać ($ 3) (4+) analogicznie do (++", world") "hello".

Dlaczego ktoś miałby to zrobić? Na przykład dla list funkcji. Oba:
map (++", world") ["hello","goodbye"]`

I:

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

Są krótsze niż map (\x -> x ++ ", world") ... lub map (\f -> f 3) .... Oczywiście, Ostatnie warianty byłyby bardziej czytelne dla większości ludzi.

 31
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-04 05:47:03

Haskell: różnica między . (kropka) i $ (Znak dolara)

Jaka jest różnica między kropką (.) a znakiem dolara ($)?. Jak rozumiem, oba są cukrem składniowym, ponieważ nie muszą używać nawiasów.

nie cukrem składniowym za to, że nie trzeba używać nawiasów - są to funkcje, - infixed, stąd możemy je nazywać operatorami.

Skomponuj, (.) i kiedy go użyć.

(.) na funkcja komponowania. Więc

result = (f . g) x

Jest tym samym co budowanie funkcji, która przekazuje wynik jej argumentu przekazany do g na f.

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

Użyj (.), gdy nie masz dostępnych argumentów do przekazania funkcjom, które chcesz skomponować.

Prawo asocjacyjne, ($), i kiedy go używać

($) jest prawo-asocjacyjną funkcją apply o niskim priorytecie wiązania. Więc najpierw wylicza rzeczy po prawej stronie. Tak więc

result = f $ g x

Jest to to samo, proceduralnie (co ma znaczenie, ponieważ Haskell jest oceniany leniwie, zacznie Oceniać f najpierw):

h = f
g_x = g x
result = h g_x

Lub bardziej zwięźle:

result = f (g x)

Użyj ($), gdy masz wszystkie zmienne do oceny, zanim zastosujesz poprzednią funkcję do wyniku.

Możemy to zobaczyć czytając źródło dla każdej funkcji.

Przeczytaj źródło

Oto źródło dla (.):

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

A oto źródło dla ($):

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

Podsumowanie

Użyj kompozycji, gdy nie musisz natychmiast Oceniać funkcji. Może chcesz przekazać funkcję, która wynika z kompozycji do innej funkcji.

Użyj aplikacji, gdy podajesz wszystkie argumenty do pełnej oceny.

Tak więc dla naszego przykładu, semantycznie lepiej byłoby zrobić]}
f $ g x

Gdy mamy x (a raczej g's argumenty) i robimy:

f . g

Kiedy Nie.

 21
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Moja zasada jest prosta (też jestem początkujący):

  • nie używaj . jeśli chcesz przekazać parametr (wywołać funkcję), oraz
  • nie używaj $ Jeśli nie ma jeszcze parametru (skomponuj funkcję)

To jest

show $ head [1, 2]

Ale nigdy:

show . head [1, 2]
 12
Author: halacsy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 12:23:38

... można też uniknąć konstrukcji . i $ za pomocą pipelining:

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

To po dodaniu w funkcji helpera:

(|>) x y = y x
 12
Author: user1721780,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 12:24:49

Świetnym sposobem, aby dowiedzieć się więcej na temat czegokolwiek (dowolnej funkcji), jest zapamiętanie, że wszystko jest funkcją! Ta ogólna mantra pomaga, ale w konkretnych przypadkach, takich jak operatorzy, pomaga zapamiętać tę małą sztuczkę:]}

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

I

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

Pamiętaj, aby używać :t swobodnie i owiń swoje operatory w ()!

 11
Author: lol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 03:58:43

Najważniejszą częścią $ jest to, że ma najniższy priorytet operatora.

Jeśli wpiszesz info zobaczysz to:

λ> :info ($)
($) :: (a -> b) -> a -> b
    -- Defined in ‘GHC.Base’
infixr 0 $

To mówi nam, że jest to operator infiksu o prawoskrętności, który ma najniższy możliwy priorytet. Normalna aplikacja funkcji jest lewostronnie asocjacyjna i ma najwyższy priorytet (10). Więc $ jest czymś odwrotnym.

Więc używamy go tam, gdzie normalne zastosowanie funkcji lub użycie () nie działa.

Więc, na przykład, to działa:

λ> head . sort $ "example"
λ> e

Ale to nie:

λ> head . sort "example"

Ponieważ . ma niższy priorytet niż sort i typ (sort "example") to [Char]

λ> :type (sort "example")
(sort "example") :: [Char]
Ale . oczekuje dwóch funkcji i nie ma ładnego krótkiego sposobu, aby to zrobić ze względu na kolejność operacji sortowania i .
 1
Author: user2415706,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-08 18:05:53

Myślę, że krótki przykład, gdzie można użyć ., a nie $ pomoże wyjaśnić rzeczy.

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

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

Zauważ, że times6 jest funkcją utworzoną ze składu funkcji.

 0
Author: Brennan Cheung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-15 23:26:42

Wszystkie inne odpowiedzi są całkiem dobre. Ale jest ważny szczegół użyteczności o tym, jak ghc traktuje $, że kontroler typu ghc pozwala na instatiarion z typami o wyższej randze/ kwantyfikowanymi. Jeśli spojrzysz na typ $ id Na przykład okaże się, że będzie ona przyjmować funkcję, której argument sam w sobie jest funkcją polimorficzną. Takie małe rzeczy nie mają takiej samej elastyczności z równoważnym operatorem. (To naprawdę sprawia, że zastanawiam się, czy $! / align = "left" / )

 0
Author: Carter Tazio Schonwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 02:59:36