![]() |
1
36
正如rjan Johansen所说,Scala不支持返回类型的方法调度。Scala对象系统构建在JVM 1和JVM之上
顺便说一句,调度是选择要调用的具体方法的过程。在Scala/Java中,所有方法都是虚拟的,也就是说,调用的实际方法取决于对象的实际类型。
在这里,即使
然而,JVM只考虑调用方法的变量的类型。例如,在没有显式检查的情况下,不可能基于运行时类型的参数调用不同的方法。例如:
这里有两个同名但参数类型不同的方法。即使
Haskell拥有高级类型系统(它与Scala相当,事实上它们都起源于 System F ,但Scala类型系统支持子类型化,这使得类型推断更加困难),这至少允许在不启用某些扩展的情况下进行全局类型推断。Haskell还具有类型类的概念,这是它用于动态多态性的工具。类型类可以松散地认为是没有继承但带有参数分派的接口 和返回值 类型。例如,这是一个有效的类型类:
然后根据调用方法的上下文,
这是一种非常强大的技术,在裸JVM对象系统中没有对应关系,因此Scala对象系统也不支持它。此外,缺少全尺寸类型推断会使此功能使用起来有些麻烦。因此,Scala标准库没有
然而,Scala类型系统及其隐式机制足够强大,可以以形式化的方式表达功能齐全的类型类,并且可以扩展为泛型monad,尽管由于在完全类型推理方面存在困难,它可能需要添加比Haskell更多的类型注释。 这是Scala中monad类型类的定义:
这是它的实现
然后可以以如下通用方式使用:
在这里
从上面可以看到,即使在Scala中,类型类也允许模拟返回类型的调度。事实上,这正是Haskell在幕后所做的——Scala和Haskell都在传递一个实现某个类型类的方法字典,尽管在Scala中,它更显式,因为这些“字典”是一级对象,可以按需导入,甚至可以显式传递,所以它并不是一个真正恰当的分派,因为它没有那么嵌入。
如果您需要此数量的泛型,可以使用
Scalaz
库,其中包含许多类型类(包括monad)及其一些常见类型的实例,包括
|
![]() |
2
9
我不认为你真的是在说Scala的monad没有单位函数,而是 名称 单位函数的值可以变化。第二张幻灯片的示例中似乎显示了这一点。 至于为什么会这样,我认为这仅仅是因为Scala在JVM上运行,而这些函数必须作为JVM方法来实现——它们唯一的标识是:
在实践中,它们通常作为
所以我想Scala至少对单元函数有一个命名约定,尽管它没有唯一的名称:
|
![]() |
3
5
Caveat:我还在学习Haskell,我在不断地编这个答案。
首先,你已经知道的-Haskell的
Borrowing this example from Wikipedia:
Scala与
但有一点不同:
因此,由于没有最后一步的“扁平化”,表达式值已经具有monad类型,因此不需要使用类似于
|
![]() |
4
1
实际上,scala中有一个返回函数。很难找到。 Scala在许多方面与Haskell略有不同。大多数差异都是JVM限制的直接后果。JVM无法根据其返回类型分派方法。因此Scala基于隐式证据引入了类型类多态性来解决这一问题。
它甚至在scala标准集合中使用。您可能会注意到
每次您想要构建自定义集合时,都应该为这个隐式编写实现。不过,写一本指南的指南并不多。我推荐你
this guide
。这说明了原因
所以您可以使用自定义集合作为示例monad,并根据提供的教程编写其他monad。 |