Cos'è lo stile "point free" (nella programmazione funzionale)?


101

Una frase che ho notato di recente è il concetto di stile "point free" ...

Prima c'era questa domanda, e anche questa .

Poi, ho scoperto che qui menzionano "Un altro argomento che potrebbe valere la pena discutere è l'antipatia degli autori per lo stile point free".

Cos'è lo stile "point free"? Qualcuno può dare una spiegazione concisa? Ha qualcosa a che fare con il curry "automatico"?

Per avere un'idea del mio livello - ho insegnato a me stesso Scheme, e ho scritto un semplice interprete Scheme ... Capisco cosa sia il curry "implicito", ma non conosco Haskell o ML.


3
Solo una nota: per vedere perché si chiama pointfree visita Pointfree / Ma pointfree ha più punti! su HaskellWiki.
Petr Pudlák

Risposte:


66

Basta guardare l' articolo di Wikipedia per ottenere la tua definizione:

La programmazione tacita (programmazione senza punti) è un paradigma di programmazione in cui una definizione di funzione non include informazioni riguardanti i suoi argomenti, utilizzando combinatori e composizione di funzioni [...] invece di variabili.

Esempio Haskell:

Convenzionale (specifichi esplicitamente gli argomenti):

sum (x:xs) = x + (sum xs)
sum [] = 0

Senza punti ( sumnon ha argomenti espliciti - è solo una piega che +inizia con 0):

 sum = foldr (+) 0

O anche più semplice: invece di g(x) = f(x), potresti semplicemente scrivere g = f.

Quindi sì: è strettamente correlato al curry (o operazioni come la composizione delle funzioni).


8
Ah! Capisco! Quindi costruisci nuove funzioni sempre solo combinando altre funzioni piuttosto che dichiarare argomenti ... Molto elegante!
Paul Hollingsworth,

22
Non mi piace davvero dover trovare nuovi nomi per variabili / argomenti durante la programmazione. Questa è una delle ragioni principali per cui amo lo stile senza punti!
Martijn

2
In che modo è correlato al curry?
kaleidic

1
@kaleidic: Perché senza avere nomi di variabili, è necessario comporre funzioni parzialmente applicate. Questo è ciò che chiamiamo curry (o, più precisamente, ciò che è reso possibile attraverso il curry)
Dario

1
Non intendi sum (x:xs) ...invece di sum sum (x:xs) ...?
Ehtesh Choudhury

33

Stile senza punti significa che gli argomenti della funzione da definire non sono menzionati esplicitamente, che la funzione è definita attraverso la composizione della funzione.

Se hai due funzioni, come

square :: a -> a
square x = x*x

inc :: a -> a
inc x = x+1

e se vuoi combinare queste due funzioni con una che calcola x*x+1, puoi definirla "point-full" in questo modo:

f :: a -> a
f x = inc (square x)

L'alternativa senza punti sarebbe non parlare dell'argomento x:

f :: a -> a
f = inc . square

22
Stupidamente, in Haskell, il modo "senza punti" è di solito quello che sembra più appuntito (più punti). Questo fastidio lo rende un eccellente mnemonico. (Il libro Real World Haskell commenta questo.)
Dan

3
Per quanto riguarda il commento di @ Dan, la pagina Pointfree HaskellWiki offre una spiegazione del motivo per cui è chiamato pointfree .
Vincent Savard

2
@ Dan: Non penso sia stupido, dato che il punto Haskell dovrebbe essere "quell'operatore del cerchio" (dovrebbe assomigliare più a ° però). Ma è fonte di confusione, specialmente quando sei nuovo ai linguaggi di programmazione funzionali; ogni libro introduttivo su haskell dovrebbe spiegare lo stile senza punti.
Sebastian Mach

12

Un esempio JavaScript:

//not pointfree cause we receive args
var initials = function(name) {
  return name.split(' ').map(compose(toUpperCase, head)).join('. ');
};

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
const join = m => m.join();

//pointfree
var initials = compose(join('. '), map(compose(toUpperCase, head)), split(' '));

initials("hunter stockton thompson");
// 'H. S. T'

Riferimento


5

Lo stile senza punti significa che il codice non menziona esplicitamente i suoi argomenti, anche se esistono e vengono utilizzati.

Questo funziona in Haskell a causa del modo in cui funzionano le funzioni.

Per esempio:

myTake = take

restituisce una funzione che accetta un argomento, quindi non c'è motivo di digitare esplicitamente l'argomento a meno che tu non lo voglia anche tu.


1
A volte, non funziona in Haskell 98, come in myShow = show. C'è di più al riguardo sul wiki Haskell
Ehtesh Choudhury

-1

Ecco un esempio in TypeScript senza altre librerie:

interface Transaction {
  amount: number;
}

class Test {
  public getPositiveNumbers(transactions: Transaction[]) {
    return transactions.filter(this.isPositive);

    //return transactions.filter((transaction: {amount: number} => transaction.amount > 0));
  }

  public getBigNumbers(transactions: Transaction[]) {
    // point-free
    return transactions.filter(this.moreThan(10));

    // not point-free
    // return transactions.filter((transaction: any) => transaction.amount > 10);
  }

  private isPositive(transaction: Transaction) {
    return transactions.amount > 0;
  }

  private moreThan(amount: number) {
    return (transaction: Transaction) => {
      return transactions.amount > amount;
    }
  }
}

Puoi vedere che lo stile senza punti è più "fluente" e più facile da leggere.


Non è uno stile senza punti, è solo una distinzione tra un lambda e una funzione denominata.
kralyk

@kralyk Penso che tu abbia perso il punto, this.moreThan(10)non è una funzione con nome, è una funzione curata così come una funzione che implicitamente (quindi senza punti) prenderà transactioncome input.
AZ.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.