2012-01-23 8 views
9
public static Func<V> To<T, V>(this Func<T> g, Func<T, V> h) 
{ 
    return() => h(g()); 
} 

public static Func<T> ToIdentity<T>(this T t) 
{ 
    return() => t; 
} 

A volte uso questi e altri per ritardare la valutazione. Sono già nella libreria .net?Esistono già costrutti C# /. NET funzionali come questi? g (h()) o

Edit:

Ecco un esempio di utilizzo:

public static string SuffixColumn(this string v, string suffix, int columns) 
{ 
    return 
    v.ToIdentity() 
     .ToScrubbedHtml() 
     .ToFormat(() => "{0} " + suffix.ToLower().PadLeft(columns, ' ')) 
     .ToErrorText(v, suffix, columns)(); 
} 

ToErrorText controlli 'v' come legittimo (codice non-errore, non nullo, ecc), se bene si corre il incatenato in Func, se cattivo produce un risultato di testo sicuro. Se v, suffisso o colonne non sono buoni allora ToFormat non verrà mai chiamato. (Da qui l'uso ritardato/non valutato).

ToFormat è quasi la composizione del Func fornito e string.Format. ToIdentity viene utilizzato per sollevare v in Func e quindi tutto nella catena si basa su alcuni Func di T.

+1

come si fa a ritardare la valutazione utilizzando il codice fornito? – Tigran

+3

La risposta breve è no. Sono curioso però. Questi sono combinatori piuttosto insoliti in quanto restituiscono metodi che non accettano argomenti. Per cosa li stai usando? Inoltre, quest'ultimo è mal chiamato; una funzione di identità ha la proprietà che il suo input è uguale al suo output, ma la funzione restituita qui non richiede input. –

+0

Grazie per il feedback - Non sono proprio sicuro di cos'altro chiamare ToIdentity. And To() dovrebbe probabilmente chiamare Compose. Ma ogni risultato in una funzione che non accetta argomenti, quindi non esattamente la stessa cosa. – lucidquiet

risposta

34

Vediamo se ho capito: si sta utilizzando lambda per catturare i valori in un oggetto "wrapper" - un Func<T> - e poi costruire un flusso di lavoro di funzioni pigramente-valutato attorno all'oggetto avvolto, sì?

enter image description here

Anche se la costruzione di fuori delle funzioni di opere, io personalmente incline a costruire la monade di un certo tipo personalizzato; sembra troppo facile confondere le funzioni che agiscono sul tipo monadico o il suo tipo "sottostante" con le istanze della stessa monade. Fondamentalmente stai creando l'identità monad usando le funzioni; Sarei più propenso a creare semplicemente una classe o un'interfaccia con un nome che rifletta lo scopo a cui stai mettendo la monade dell'identità.

Si potrebbe anche prendere in considerazione la possibilità di rinominare i propri metodi. Il tuo "A" è tradizionalmente chiamato "Bind" e la tua "ToIdentity" è tradizionalmente chiamata "Unità".

Cioè, un modello Monade per un tipo monad M<T> solito ha metodi:

public static M<V> Bind<U, V>(this M<U> m, Func<U, M<V>> k) 

e

public static M<T> Unit<T>(this T value) 

bind permette di implementare composizione di funzioni di monadi analoghi a funzioni che compongono i tipi "sottostanti" delle monadi.

Per una breve introduzione alle meraviglie di monadi in C#, vedere la grande articolo del mio collega ex Wes Dyer sul tema:

http://blogs.msdn.com/b/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx

Per rispondere alla tua domanda effettiva:

Sono già nella libreria .net?

Queste funzioni esatte non sono nel quadro. Ma funziona molto come quelli che esistono nel framework. Ad esempio, SelectMany su IEnumerable<T> è analogo al metodo To; implementa l'operazione di bind monadica sulle sequenze. new Nullable<int>(123) è analogo al metodo "ToIdentity"; implementa l'operazione dell'unità monadica per la "forse monade". E così via.

Il sistema di tipo CLR non è sufficientemente ricco per esprimere il modello di monade in generale; per questo è necessario un sistema di tipo "più alto", come quello di Haskell. Dovrai costruire personalmente ciascuna monade specifica. Tuttavia, sembra che tu stia bene sulla tua strada.

Alcune ulteriori riflessioni sull'uso monadi in C# -come lingue:

Monads in C# -- why Bind implementations require passed function to return a monad?

Monad in plain English? (For the OOP programmer with no FP background)

Why there is no something like IMonad<T> in upcoming .NET 4.0

Help a C# developer understand: What is a monad?

+0

Intelligente per riconoscere questi in una forma mascherata. – jason

+9

lol a clippy: D –

+0

Ora c'è una caratteristica che VS ha davvero bisogno di ottenere. XCode ed Eclipse non sarebbero mai in grado di competere. – MgSam

2

È possibile utilizzare i valori lazy-load da Lazy.

Lazy<int> lazy = new Lazy<int>(() => delayEvaluatingMe()); 
int delayed = lazy.Value; 
+0

Questo non risponde nemmeno alla domanda. – jason

Problemi correlati