2013-07-31 10 views
8

W odpowiedzi https://stackoverflow.com/a/11006842/1065190 ona „Sowa” wymienia się:W jaki sposób "operator boobs" Haskella działa w zwykłym niefunkcjonalnym języku angielskim?

absoluteError = ((.) . (.)) abs (-) 

wyrazić absolutną funkcji błędu w punkcie wolne zapisu.

W każdym razie, jak działa ta notacja?

Czy mógłbyś, proszę, wyjaśnić to niefunkcjonującemu programiście C++?

+1

Patrząc typu pouczające: (...()()) :: (B -> C) -> (A -> A1 -> b) -> A -> A1 -> c – dorchard

+2

Ale dlaczego "cycki"? –

+3

@SergeyK .: czy to poważne pytanie? :) –

Odpowiedz

10

Tak po prostu jak to możliwe (.).(.), również napisane (.:), jest składem funkcji, gdy funkcja składająca się z prawej strony ma dwa brakujące argumenty. Jeśli spróbujesz bezpośrednio użyć polecenia (.), to nie będzie to typowe sprawdzanie, chociaż jest dość kuszące ze względu na pomysł funkcjonalnego "hydraulika".


Również, to warto pomyśleć o tym, jak (.:) niby przeciwieństwo wodociągowej z Data.Function.on.

flip on :: (a -> b) -> (b -> b -> c) -> (a -> a -> c) 
(.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b) 

on wykorzystuje jednoskładnikowa funkcję przekształcić dwa wejścia z funkcji binarnej. (.:) przyjmuje funkcję binarną i wykorzystuje ją do przekształcenia funkcji jednoargumentowej w funkcję binarną.

+3

: P Jesteś jednym akapitu odpowiedź bije moje pełne rozszerzenie/zmniejszenie funkcji zaangażowanych, nie fair – jozefg

+0

Oszukałem :) Już napisałem, że całe wyjaśnienie redukcji przed, więc gdy @SergeyK powiedział, że chciałby niefunkcjonalny odpowiedź Wiedziałem dokładnie brakujący element. –

+0

@tel: dlaczego nie używać tylko '' f (g a b) '' as @jozefg shoed w swojej odpowiedzi? –

11

Zajmuje 2 funkcje: f i g. To daje 2 argumenty g a następnie przekazuje wynik do f lub

owl f g a b = f (g a b) 

W typów to

(a -> b) -> (c -> d -> a) -> c -> d -> b 

To pozwoli to nam uniknąć nazywania wartości pośrednie w dłuższych kompozycjach funkcji, ponieważ wiele kod Haskell jest napisane coś

foo = bar . baz . quux 1 

teraz powiedzieć chcieliśmy foo dać quux 2 nie argumenty 1 ,

foo a b = let res = quux a b in 
       bar . baz $ res 

To jest tak irytująco długi w porównaniu do tego, co mamy przed zamiast możemy napisać

(.:) = owl -- give a nice operator name 
foo = bar . baz .: quux 

który jest znacznie czystsze.

Długa (mylące) wyjaśnienie jak to działa:

No . jest funkcja realizowana tylko coś takiego

(.) f g = \a -> f (g a) 

Więc ((.) . (.)) tylko

compose = (.).(.) 
compose a = (.) ((.) a)       -- expand the middle . 
compose a = (.) (\g v -> a (g v))    -- Expand the second (.) 
compose a = \g' v' -> (\g v -> a (g v)) (g' v') -- expand the first (.) 
compose a = \g' v' -> (\v -> a (g' v' v)) -- apply the first lambda to the second 
compose a g' v' v = a (g' v' v) -- Currying let's us move the arguments to 
           -- the other side 

lub kiedy zastosuj go w swoim przykładzie:

f = compose abs (-) 
f = \v' v -> abs ((-) v' v) 
f a b = abs ((-) a b) 
f a b = abs (a - b) 
+1

Czy możesz wyjaśnić to w sposób niefunkcjonalny? –

+1

To nie jest naprawdę funkcjonalne. Po prostu rozszerzam funkcję ręcznie, pstrykam i czytam, to jest naprawdę takie samo jak w C++ z bardziej zwięzłą składnią: – jozefg

+1

@SergeyK .: jak wyjaśnić funkcję wyższego rzędu w "niefunkcjonalnym" droga? –

6

Zakładając można przeczytać notacji lambda w Haskell, jest to bardzo proste:

\arguments -> body 

tak proste wyrażenia mogą być:

\x -> x+1 

\x y -> x+y 

Lambdabot ma command pointful które można przekształcić pointfree do funkcji pointful. Wyrażony jako proste wyrażenie lambda staje się całkiem wyraźną funkcją wyższego rzędu.

$ pointful "((.) . (.))" 

(\ i b c f -> i (b c f)) 

Więc co to zrobić w języku angielskim, to zajmuje funkcję w swoim pierwszym argumencie „ja” i odnosi się to do wyniku innej funkcji „b” stosowanej do argumentów „C” i „f”.

Tak naprawdę to ta funkcja po normalizacji go:

$ pointful "((.) . (.)) abs (-)" 

(\ c f -> abs (c - f)) 

co jest dość łatwe do zrozumienia, jak to jest absolutny błąd.

Jeśli chcesz zobaczyć pochodzenie tego, co Lambdabot robi za kulisami, zobacz: this post, która jest jedynie pozornie beta-redukcją terminów lambda. Jedyną częścią Sztuką jest to, że mamy do mieszania operatorów Infix i przedrostek, ten sam termin może być napisane jaśniej jak:

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

Wtedy staje się jasne, że jest to po prostu „kompozycja składu function”.

+4

+1 dla Lambdabot –

Powiązane problemy