2009-12-04 11 views
9

Il seguente codice è in Haskell. Come scriverei una funzione simile in C#?Apprendimento Haskell: list comprehensions in C#

squareArea xs = [pi * r^2 | r <- xs] 

Giusto per chiarire ... codice sopra è una funzione, che prende in ingresso un elenco contenente raggio di cerchi. L'espressione calcola l'area di ciascun cerchio nell'elenco di input.

So che in C#, posso ottenere lo stesso risultato, eseguendo il ciclo attraverso un elenco e calcolando l'area di ciascun cerchio nell'elenco e restituire un elenco contenente un'area di cerchi. La mia domanda è ... Il codice sopra può essere scritto in modo simile in C#, forse usando espressioni lambda o LINQ?

+0

Aspetta, hanno una funzione che inizia con la A maiuscola? Questo è illegale? – codebliss

+0

Perché calcoli l'area con 2 * pi * r? Non è pi * r^2 o pi * r ** 2 la strada da percorrere? – Long

+1

'2 * pi * r' calcolerà la circonferenza di un cerchio, non la sua area. –

risposta

22

Utilizzando Enumerable:

IEnumerable<double> SquareArea(IEnumerable<int> xs) 
{ 
    return from r in xs select Math.PI * r * r; 
} 

o

IEnumerable<double> SquareArea(IEnumerable<int> xs) 
{ 
    return xs.Select(r => Math.PI * r * r); 
} 

che è molto vicino a Haskell

squareArea xs = map (\r -> pi * r * r) xs 
+1

non sarebbe più semplice non usare le espressioni Lambda? 'squareArea xs = map (2 * pi *) xs' –

+0

Sicuro. Puoi anche accorciarlo 'squareArea = map (2 * pi *)' Ma non è molto più vicino a C#. – dtb

+2

o 'squareArea = map ((* pi). (^ 2))' con la formula corretta – dtb

6
xs.Select(r => 2 * Math.PI * r * r) 

è il lato destro, credo (scrivendo codice nel mio browser, non compilato).

In generale, un elenco Haskell comprensione del modulo

[e | x1 <- x1s, x2 <- x2s, p] 

è probabilmente qualcosa di simile

x1s.SelectMany(x1 => 
x2s.SelectMany(x2 => 
if p then return Enumerable.Singleton(e) else return Enumerable.Empty)) 

o

from x1 in x1s 
from x2 in x2s 
where p 
select e 

o qualcosa del genere. Maledizione, non ho il tempo di sistemarlo ora, qualcun altro per favore (contrassegnato con la community Wiki).

4

DTB ha probabilmente la migliore versione finora, ma se si ha un un po 'più lontano e ho messo i metodi in una classe statica e ho aggiunto questo operatore come il seguente che potresti cal cal l metodi come se fossero una parte della vostra lista:

public static class MyMathFunctions 
{ 
    IEnumerable<double> SquareArea(this IEnumerable<int> xs) 
    { 
     return from r in xs select 2 * Math.PI * r * r; 
    } 

    IEnumerable<double> SquareAreaWithLambda(this IEnumerable<int> xs) 
    { 
     return xs.Select(r => 2 * Math.PI * r * r); 
    } 

} 

che potrebbero poi essere eseguito in questo modo:

var myList = new List<int> { 1,2,3,4,5 }; 

var mySquareArea = myList.SquareArea(); 
+0

Entrambi i metodi SquareArea sono uguali? I miei occhi non riescono a individuare la differenza :( – chollida

+1

Sì, intendevo includere: da r in xs selezionare 2 * Math.PI * r * r; nel primo metodo, ho modificato il mio post in rifletterlo –

2
Func<IEnumerable<Double>, IEnumerable<Double>> 
    squareArea = xs => xs.Select(r => Math.PI*r*r); 
Problemi correlati