Domanda

... con tutti quelli nuovi (e non così nuovo se contiamo IEnumerable) roba monade legati?

interface IMonad<T>
{
 SelectMany/Bind();
 Return/Unit();
}

Ciò consentirebbe di scrivere funzioni che operano su qualsiasi tipo monade. O non è così critico?

È stato utile?

Soluzione

Pensate a quello che la firma per i metodi di IMonad<T> avrebbe dovuto essere. In Haskell la typeclass Monade è definito come

class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  return :: a -> m a

E 'difficile da tradurre questo direttamente a un'interfaccia C #, perché è necessario essere in grado di fare riferimento al sottotipo specifico recante attuazione ( "m a" o ISpecificMonad<a>) all'interno della definizione dell'interfaccia generale IMonad. OK, invece di cercare di avere (per esempio) IEnumerable<T> implementare direttamente IMonad<T>, cercheremo di factoring l'attuazione IMonad fuori in un oggetto separato, che può essere passato, insieme alla specifica istanza del tipo di monade, a tutto ciò che ha bisogno di trattarlo come un monade (questo è "stile dizionario-passing"). Questo sarà IMonad<TMonad> e TMonad qui non sarà il T in IEnumerable<T>, ma si IEnumerable<T>. Ma aspettate - questo non può funzionare sia, perché la firma di Return<T> ad esempio, ha di farci da qualsiasi tipo T ad un TMonad<T>, per qualsiasi TMonad<>. IMonad avrebbe dovuto essere definito come qualcosa di simile

interface IMonad<TMonad<>> {

    TMonad<T> Unit<T>(T x);
    TMonad<U> SelectMany<T, U>(TMonad<T> x, Func<T, TMonad<U>> f);
}

utilizzando una funzionalità ipotetica C # che ci permetterebbe di utilizzare costruttori di tipo (come TMonad <>) come parametri di tipo generico. Ma, naturalmente, C # non ha questa funzione (polimorfismo superiore kinded) . È possibile reificare costruttori di tipo in fase di esecuzione (typeof(IEnumerable<>)), ma non può fare riferimento a loro in tipo firme senza dare loro parametri. Quindi oltre la cosa -100 punti, l'attuazione del presente "correttamente" richiederebbe non solo l'aggiunta di un'altra definizione di interfaccia comune, ma le aggiunte profonde al sistema tipo.

Ecco perché la capacità di avere comprensioni di query oltre i propri tipi è una specie di hacked su (hanno solo lavoro "magicamente", se i nomi giusti metodo magico con le firme di destra ci sono) invece di utilizzare il meccanismo di interfaccia, ecc.

Altri suggerimenti

Monadi semplicemente non sono importanti per i programmatori .NET. Senza nemmeno sapere monadi esistono si può ancora costruire il quadro LINQ. Ancora più importante, non apparirebbe diverso. Non importa se si pensa in termini di monadi (Haskell), albero di espressione riscrittura (Lisp), le operazioni basate su set (SQL), o usando la mappa / ridurre a creare nuovi tipi (Ruby, Python), il risultato finale è sta per essere lo stesso.

In realtà, vorrei andare fino al punto di dire che le monadi sono decisamente inutili per sviluppatori .NET. Ogni volta che vedo una libreria per NET sulla base di monadi, è invariabilmente sia più prolisso e meno comprensibili di dritto C # o codice VB. La ragione è semplice, linguaggi come C # e VB sono costruite su molto, molto più potenti blocchi di costruzione di linguaggi come Haskell.

Haskell, in particolare, ha bisogno di usare monadi di tutto perché questo è tutto quello che hanno. Lo stesso vale per le macro in Lisp o tipizzazione dinamica in JavaScript. Quando si ha un one-trick pony, quel trucco deve essere dannatamente bene.

On LINQ , Monadi, e la cecità del potere

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top