Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么没有像伊莫纳德这样的东西<;T>;在即将发布的.NET4.0中_C#_.net_Monads - Fatal编程技术网

C# 为什么没有像伊莫纳德这样的东西<;T>;在即将发布的.NET4.0中

C# 为什么没有像伊莫纳德这样的东西<;T>;在即将发布的.NET4.0中,c#,.net,monads,C#,.net,Monads,。。。所有这些新的(如果我们算上IEnumerable的话,也不是那么新的)单子相关的东西 interface IMonad<T> { SelectMany/Bind(); Return/Unit(); } 接口IMonad { 选择many/Bind(); 返回/单位(); } 这将允许编写在任何一元类型上运行的函数。或者它不是那么重要?想想IMonad方法的签名应该是什么。在Haskell中,Monad类型类定义为 class Monad m where (>&

。。。所有这些新的(如果我们算上IEnumerable的话,也不是那么新的)单子相关的东西

interface IMonad<T>
{
 SelectMany/Bind();
 Return/Unit();
}
接口IMonad
{
选择many/Bind();
返回/单位();
}

这将允许编写在任何一元类型上运行的函数。或者它不是那么重要?

想想
IMonad
方法的签名应该是什么。在Haskell中,Monad类型类定义为

class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  return :: a -> m a
将其直接转换为C#接口很难,因为您需要能够在通用IMonad接口的定义中引用特定的实现子类型(“MA”或
isSpecificMonad
)。好的,我们将尝试将IMonad实现分解成一个单独的对象,该对象可以与特定的monad类型实例一起传递给任何需要将其作为monad处理的对象(这是“字典传递样式”)。这将是
IMonad
,这里的TMonad将不是
IEnumerable
中的T,而是
IEnumerable
本身。但是等等——这也不行,因为对于任何
TMonad
,例如
Return
的签名必须将我们从任何类型的t转换为
TMonad
。伊莫纳德必须被定义为

interface IMonad<TMonad<>> {

    TMonad<T> Unit<T>(T x);
    TMonad<U> SelectMany<T, U>(TMonad<T> x, Func<T, TMonad<U>> f);
}
接口IMonad{
TMonad单元(tx);
TMonad SelectMany(TMonad x,Func f);
}
使用一个假设的C#特性,允许我们使用类型构造函数(比如TMonad)作为泛型类型参数。当然,C#没有这个特征(更高级的多态性)。您可以在运行时具体化类型构造函数(
typeof(IEnumerable)
),但不能在类型签名中引用它们,而不给它们参数。因此,除了-100点之外,实现这个“正确”不仅需要添加另一个普通接口定义,还需要对类型系统进行深入的添加


这就是为什么对自己的类型进行查询理解的能力被黑客攻击的原因(如果有正确的魔法方法名和正确的签名,它们就“神奇地”起作用),而不是使用接口机制等。

monad对.NET程序员来说根本不重要。即使不知道monad的存在,您仍然可以构建LINQ框架。更重要的是,它看起来不会有任何不同。不管您是从monad(Haskell)、表达式树重写(Lisp)、基于集合的操作(SQL)还是使用map/reduce创建新类型(Ruby、Python)的角度考虑,最终结果都是一样的

事实上,我甚至可以说Monad对.NET开发人员来说是完全无用的。每次我看到一个基于monad的.NET库时,它总是比直接的C#或VB代码更冗长,更难理解。原因很简单,像C#和VB这样的语言是建立在比Haskell这样的语言功能强大得多的构建块上的

Haskell尤其需要在任何事情上使用monad,因为这就是他们所拥有的一切。Lisp中的宏或JavaScript中的动态键入也是如此。当你有一匹只有一个技巧的小马时,这个技巧必须非常好


Eric Lippert解释了为什么框架中没有实现某些功能:回答得好,这里有一个简短的版本:“不可能在C#中定义Monad,类型系统不够强大”:)因此,可能在CLR 5.0或6.0中,或者在更高抽象级别的后.NET运行时中。在我个人看来,如果没有静态检查的副作用(即纯函数),那么在相当快地向类型系统添加更复杂的内容时,您的回报将严重减少。复杂类型系统的真正好处是能够建立程序的复杂属性/不变量,这些属性/不变量在所有情况下都被证明是有效的(而不是在某些情况下被测试为有效并从中进行启发式推断),但是如果任何函数具有额外的不受限制的“通道”对于类型系统未检查的输入/输出,您无法证明多少。@MikeHadlow,我不会说“不可能”,而只是很麻烦。您必须预先创建一个多继承层次结构(当然是接口的层次结构),以便在编译时描述每个具体类可以操作的允许类型,每个IMonad有一个汇总接口。我不确定这一限制是否与Max完全背道而驰,但就我个人而言,我认为这一原则对于一个人的特定领域来说将是一个坚实的练习。我会让你知道事情的进展:P@MaxStrini,我不同意,我认为Monad是一个有用的抽象,它超越了Haskell中的杀手级应用,即IO Monad。Scala有一个类型系统,支持非严格的多范式语言中的单子,他们显然发现它很有用。“原因很简单,像C#和VB这样的语言建立在比Haskell这样的语言更强大的构建块上。”说这句话表明你从未在Haskell编程或完全了解它的概念。值得否决票,如果只是因为包含了“私人博客”的链接。这不值得否决票。无论如何,这个问题需要一种固执己见的观点。他给出了反对C#中单子的正当理由。这一评论被否决,因为它表明了对单子的误解。它不是一种编程的风格或接口,也不是其他任何东西。它是对某一类型的某些属性的描述,这是具体的。这是数学真理。对于.NET程序员来说,了解或理解单子是不重要的,这当然是有争议的,一个人不需要考虑单子来做大量的事情,这是正确的,但是最终的结果不一定是一样的-使用单子可以实现即使不是不可能也很难的合成,但我并没有说单子是可组合的。我声称使用monads