11

Mam problem ze zrozumieniem, w jaki sposób działa aplikacja funkcyjna z curry w haskell. Jeśli mam następujące funkcję:Aplikacja operatora dolara Haskella

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

Rozumiem, że częściowo zastosować tę funkcję muszę dostarczyć (a -> b) funkcję ($ „s pierwszy argument).

Dlaczego więc można najpierw zastosować wartość (tzn. Odwrócić argumenty)?

($ 0) :: Num a => (a -> b) -> b 

Czego tu mi brakuje?

Odpowiedz

13

($) jest operatorem. W Haskell, każdy podmiot może być napisana w lewej sekcji (np (x $)) lub prawy odcinek (jak ($ x)):

(x $) = (\y -> x $ y) = ($) x 
($ x) = (\y -> y $ x) = flip ($) x 

Należy zauważyć, że jedynym wyjątkiem od tej reguły jest (-), w celu wygodnie pisać liczb ujemnych:

\x -> (x-) :: Num a => a -> a -> a -- equivalent to \x -> (-) x 
\x -> (-x) :: Num a => a -> a  -- equivalent to \x -> negate x 

w przypadku chcesz, aby krótko napisać (\y -> y - x), można użyć subtract:

\x -> subtract x :: Num a => a -> a -> a -- equivalent to \x -> flip (-) x 
+0

Dzięki, to wyjaśnia, dlaczego działa w ten sposób. Czy są to definicje funkcji językowych, czy można je znaleźć gdzieś w źródłach? – Rumca

+2

@Rumca Naprawdę nie w źródle, (x $) i ($ x) to sekcje, a ich opis można znaleźć w [raporcie haskell 2010] (http://www.haskell.org/onlinereport/haskell2010/) w sekcji [sekcje] (http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-300003.5). – Davorak

+0

Język został opisany w [Raporcie Haskella 2010] (http://www.haskell.org/onlinereport/haskell2010/). –

4

($ 0)(\x -> x $ 0)(\x -> ($) x 0)

Jeśli ($) :: (a -> b) -> a -> b) i zastosowano drugi argument jak (\x -> ($) x 0) mamy :: Num a => (a -> b) -> b

2

Mylicie zapis infiksowania operatora z funkcją.

> :t (($) (+1)) 
(($) (+1)) :: Num b => b -> b 

Oto niektóre formy wyrazu z $, dla lepszego zrozumienia:

$ b => ($) ab

($ B) => Flip ($) b => (\ BA -> ($) AB) b => \ o -> ($) AB

(a $) => ($) a => \ b -> ($) AB

+0

-1 Nawet ta osoba, która mocno rozumie, o co chodzi w tym pytaniu i jakie jest jego uzasadnienie, uważa tę odpowiedź za niezrozumiałą. Jak ktoś, kto nie zna Haskella, bardzo dobrze ma to rozumieć? Brak wyjaśnienia, jaka jest różnica między operatorami i funkcjami. '$ b => flip ($) b => \ a -> ($) a b' nie jest poprawną składnią. (Edycja: W porządku, będzie to -1, gdybym miał trochę więcej przedstawicieli.) –

1

Należy również zauważyć, że w składni Haskella nazwy alfanumeryczne są odróżniane od nazw interpunkcji.

Funkcja alfanumeryczna foo1 a b jest domyślnie prefiksem i staje się infiksem, jeśli dodasz odnośniki: a `foo` b.

Funkcja interpunkcyjny nazwie jak $ lub <*> Wrostek jest domyślnie i staje prefiks jeśli dodać nawiasy ($) lub (<*>). To jest po prostu cukier składniowy dla programisty znającego alfabet łaciński; jest to arbitralne, ale pomocne rozróżnienie między nazwami alfanumerycznymi a nazwami interpunkcyjnymi.

Oba rodzaje funkcji są po prostu funkcjami, nie mają specjalnych reguł semantycznych, które mamy dla "operatorów" w C++ lub Java. Są to tylko reguły składniowe dotyczące przedrostka/infiksu i zwrotów/nawiasów, które różnią się między funkcjami interpunkcyjnymi a funkcjami alfanumerycznymi.