Piense acerca de lo que la firma de IMonad<T>
's métodos tendría que ser. En Haskell la clase de tipos Monad se define como
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
Es difícil de traducir esta directamente a una interfaz de C# porque es necesario para poder hacer referencia al subtipo particular de aplicación ("ma" o ISpecificMonad<a>
) dentro de la definición de lo general Interfaz IMonad. Aceptar, en lugar de tratar de tener (por ejemplo) IEnumerable<T>
implemento IMonad<T>
directamente, vamos a tratar de factorizar la implementación IMonad a cabo en un objeto separado que se puede pasar, junto con la instancia de tipo mónada específica, a lo que hay que tratarlo como una mónada (esto es "estilo de paso de diccionario"). Esto será IMonad<TMonad>
y TMonad aquí no será la T en IEnumerable<T>
, pero sí IEnumerable<T>
. Pero espera - esto tampoco puede funcionar, porque la firma de Return<T>
por ejemplo tiene que llevarnos desde cualquier tipo T a un TMonad<T>
, para cualquierTMonad<>
. IMonad tendría que ser definido como algo parecido a
interface IMonad<TMonad<>> {
TMonad<T> Unit<T>(T x);
TMonad<U> SelectMany<T, U>(TMonad<T> x, Func<T, TMonad<U>> f);
}
utilizando una hipotética característica C# que nos permitirá usar constructores de tipo (como TMonad <>) como parámetros de tipo genérico. Pero, por supuesto, C# no tiene esta característica (polimorfismo de alto grado). Puede reificar constructores de tipo en tiempo de ejecución (typeof(IEnumerable<>)
) pero no puede hacer referencia a ellos en las firmas de tipo sin darles los parámetros. Por lo tanto, además del punto -100 puntos, implementar esto "correctamente" requeriría no solo agregar otra definición de interfaz ordinaria, sino adiciones profundas al sistema de tipo.
Es por eso que la capacidad de tener consultas de comprensión sobre sus propios tipos es pirateada (simplemente funcionan "mágicamente" si los nombres de métodos mágicos correctos con las firmas correctas están ahí) en lugar de usar el mecanismo de interfaz, etc.
Eric Lippert explica por qué algunas características no están implementadas en el marco: http://stackoverflow.com/questions/1331739/enum-type-constraints-in-c/1331811#1331811 –