为什么Scala没有IO Monad?

26

我在想为什么Scala没有像Haskell那样的IO Monad。

因此,在Scala中,方法readLine的返回类型是String,而在Haskell中,可比较的函数getLine的返回类型为IO String。

关于这个主题有一个类似的问题,但它的答案并不令人满意:

在Scala中,使用IO明显不是主流风格。

有人能进一步解释一下吗?为什么Scala没有包括IO Monads的设计决策是什么?


10
getLine没有“返回类型IO String”。getLine的类型就是IO String。因为没有箭头符号“->”,所以它不是一个函数。 - newacct
7
或者它是一个“零元函数”。无论哪种方式都是一种有效的思考方式。 - Ben
4
@Ben 在 Haskell 中并不存在所谓的“零元函数”。 - ivanm
3
@Ben:看看在Haskell中“一切皆为函数”的文章吧。 - ehird
5
@Ben:可以说Integer是零元的;然而,它不是一个函数。同样地,我们可以定义一个类型被称为“深度 n”,意味着嵌套在 n[] 中。Integer 的深度为0,[Integer] 的深度为1,[[Integer]] 的深度为2,但只有后两种类型是列表。 - ehird
显示剩余8条评论
1个回答

38
由于Scala不是纯函数式语言(没有像D语言那样强制执行函数的纯度,并允许副作用),它与Java密切配合(例如重用了Java库的大部分)。Scala不是惰性求值的,因此不存在类似于Haskell中的执行顺序问题(例如不需要使用>>seq)。在这些情况下,引入IO Monad会使生活更加艰难,而收益却不大。

但是,如果您真的有应用程序需要IO monad的显着优势,则可以编写自己的实现或使用scalaz。请参见例如http://apocalisp.wordpress.com/2011/12/19/towards-an-effect-system-in-scala-part-2-io-monad/

[编辑]

为什么不将其设计为惰性和纯粹的语言?

这样做完全有可能(例如参考Frege,一种与Haskell非常相似的JVM语言)。当然,这会使Java的互操作性更加复杂,但我认为这不是主要原因。我认为懒惰和纯净的语言是一件很酷的事情,但对大多数Java程序员来说太陌生了,而他们是Scala的目标受众。Scala被设计成与Java的对象模型合作(这与纯粹和懒惰完全相反),允许函数式和混合的函数式-面向对象编程,但不强制要求(否则几乎所有Java程序员都会离开)。实际上,拥有又一个完全函数式的语言是没有意义的:有Haskell、Erlang、F#(和其他ML语言)以及Clojure(和其他Scheme / Lisp语言),它们都非常复杂、稳定和成功,并不容易被新手所取代。

那么主要原因是Java的互操作性吗?或者为什么它不作为一种惰性和纯粹的语言来完成呢? - kiritsuku
3
@Antoras,JVM和其字节码没有内置的惰性和纯度支持。这意味着每次调用非Scala方法都必须在IO单子中进行,并使用严格参数,这会使Java互操作性非常困难。 - dflemstr
4
F#实际上更像Scala——它是不纯的和惰性求值的,只是需要明确声明(但我没有使用过F#,可能说得不准确)。 - Vladislav Zorov
在 Haskell 中,“>>” 对于执行顺序并没有太多作用,只有“seq”和“pseq”才具有影响。 - alternative
@alternative,所以 putStrLn "First" >> putStrLn "Second" 没有明确定义的执行顺序? - pat
@pat 并不是说它没有“明确定义”的执行顺序,只是该顺序不会因为 >> 而改变。同时请记住,>> 是用于单子而非 IO,因此任何与 IO 相关的细节都不适用。单子并不是严格的,这就是为什么我们有具有不同语义的不同单子的严格版本的原因。 - alternative

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接