jcc*_*333 3 erlang scala hindley-milner actor-model akka
所以我只最近遇到一个玩具容量的阿卡之外,我不禁注意到它和OTP尽管Scala的静态类型的一般优先股动态类型.我开始挖掘一下,并且遇到了这篇描述HM型系统而非erlang进程间通信的Wadler论文.也就是说,SO的这个问题的答案是指Wadler和Marlow未能提供他们对过程类型通信的草图.作为参考,我对这样的代码感到非常失望:
def receive = {
case "test" => log.info("received test")
case _ => log.info("received unknown message")
}
Run Code Online (Sandbox Code Playgroud)
我知道在实践中,透析器可以提供真实类型系统的大量好处,但为什么创建静态验证的演员系统这么困难呢?当我们使用类型系统时,我们是倾向于编写Future或Observable/ Iteratee库,或者是Channel编程的IO而不是演员系统,还是Wadler和Marlow错过了技术难度?
将类型安全带入Akka演员的世界已经多年来一直在讨论和研究.目前正在进行的努力表现为Akka Typed API,该API可能会发生变化.
除了链接文档之外,几年前对Akka用户列表进行了精彩的讨论(标题为"我如何通过有类型的编程协调无类型的演员?")进一步深入了解了类型化的演员.在这里阅读整个讨论的整个背景,但下面是一些摘录:
来自Derek Wyatt:
你所经历的是一种权衡.演员提供了一个你似乎没有考虑到的权衡; 端点(Actors)是无类型的,它们处理的消息是强类型的.
您不能让Actor能够使用特定于类型的接收方法处理"任何东西".使用Actor编程,我应该能够在消息流中添加尽可能多的中介,而不是打扰两个端点.中间人同样应该不知道发生了什么(负载平衡器,路由器,记录器,cachers,调解器,分散 - 聚集等等).您还应该能够在群集中移动它们而不会干扰端点.您还可以在Actor中设置动态委托,而无需真正理解正在发生的事情 - 例如,演讲者说"主要方言",但在不理解所说内容时委托给其他人.
如果你想要消除所有这些功能,那么你将能够获得你正在寻找的类型安全的确定性(只要你留在同一个JVM中 - 穿越JVM就会产生"我真的到底是什么说话?"消除编译时保证的问题)....
简而言之,你放弃了类型安全,以打开一整套新设施的大门.不想失去类型安全吗?关门 :)
来自Endre Varga:
问题是类型系统是为本地计算而非分布式计算而设计的.我们来看一个例子.
想象一个有三种状态的演员,A,B和C.
- 在状态A中,它接受类型为X的消息,当接收到消息时,它将转换为B.
- 在状态B中,它接受类型为X和Y的消息.当接收到X时,如果是Y则转换到C,然后保持在B中
- 在状态C中,它接受Z类型的消息
现在你从状态A开始向一个演员发送消息X.有两件事情可能发生:
- X已交付,因此可能接受的类型为{X,Y}
- X丢失了,所以接受的类型是{X}
它们的交集是{X}.
现在假设您发送另一条消息X.可能会发生三件事:
- 两个X都交付了,所以接受的类型是{Z}
- 只有一个X被交付,另一个丢失了,所以接受的类型是{X,Y}
- 两个X都丢失了,接受的类型是{X}
上述情况的交集是空集.
那么,你发送了两个X型消息的actor的本地类型表示应该是什么?
让我们修改这个例子,并假设没有消息丢失,但让我们采取另一个发送者的观点.此发件人知道另一个发件人已将两个X发送给我们的示例actor.我们可以发送什么消息?有三种情况:
- 其他发件人发送的X都已到达,因此接受的类型为{Z}
- 只有其他发件人发送的第一个X已经到达,所以接受的类型是{X,Y}
- 没有X已经到了,接受的类型是{X}
上述情况的交集是空集.
如你所见,没有收到演员的回复,演员的可证明类型通常是Nothing,或者是无用的东西.只有回复可以传达演员的可能类型,如果有并发发件人,甚至无法保证.
来自Roland Kuhn博士:
我很高兴你提出这个讨论,我希望为Akka添加一定程度的静态类型,这与我参与项目一样古老.如果你看看1.x过去,你会发现akka.actor.Channel [T],这是考虑到这一点,并且在2.1和2.2中有类型频道作为基于宏的实验.后者实际上从思想实验到代码,我们欢迎您尝试一下,以了解静态类型如何与一个非常动态的系统进行交互.
Typed Channels的主要缺点是它的复杂性不合适(类型参数太多,类型太复杂 - 带有类型级列表和映射).我们正在逐渐融合到可能达到适当平衡的设计上,但实质上它意味着
sender从Akka演员中移除(在未来变换中关闭事物还有其他非常受欢迎的好处).它的要点是使用它接受的消息类型来参数化ActorRef [T](对Props [T],Actor [T]等具有明显的连锁效应).然后,Actor可以使用适当的类型公开对自身的引用,并将其发送给其他actor - 在特定的消息中以便绕过类型擦除.这甚至可以允许制定消息协议,即会话类型或至少接近它.Derek对于演员模型如何从类型不受约束中获益非常有用:消息路由器不一定需要了解通过它的消息.参数化路由器本身的工作情况还有待观察,但一般来说这样的路由阶段会破坏类型信息,我们在那里做的不多.你的观点是,进行一些类型检查比没有更好是一个能与我产生共鸣的,只要差异对于开发人员来说是显而易见的:我们必须避免错误的安全感.
这让我得到了Endre的有效感叹词,即静态验证无法访问并发行为.问题比消息丢失更广泛,因为任何非确定性行为都必须导致类型析取,通过类型结构的指数爆炸杀死我们的好静态类型.这意味着我们只能实际使用类型来表示那些确定性的部分:如果你向一个actor发送一个类型为A的消息,那么你可能会得到一个B类消息(转换为必须提供一个ActorRef [B]在A消息中),其中A和B通常是总和类型,如"此actor接受的所有命令"和"可能发送的所有回复".不可能对actor的定性状态变化进行建模,因为编译器无法知道它们是否实际发生.
但是有一些亮点:如果您收到消息B,其中包含来自目标的ActorRef [C],那么您有证据表明消息A的效果已经发生,因此您可以假设演员现在处于这样的状态:它接受消息C.但这不是保证,演员可能在此期间崩溃.
请注意,这些都不依赖于远程消息传递.你将演员分成并发和分发部分的愿望是非常易于理解的,我曾经有同样的想法.然后我开始意识到并发和分布实际上是同一个事情:如果进程在空间或时间上分离,这意味着分布,那么进程只能同时运行,另一方面,光的有限速度意味着分布式进程根据定义,它将是并发的.我们希望对我们的actor进行封装和分区,只使用消息进行通信,这个模型意味着两个actor总是彼此分离,即使它们在同一个JVM上运行它们也是分布式的(队列可以运行完全,可能发生故障,通信虽然它的可靠性肯定比网络情况高很多,但并不完全可靠.如果你考虑现代处理器,不同的核心,特别是插座也是由网络分开的,它们比你爷爷的千兆以太网快得多.
这就是为什么我认为Actor模型恰好是现在和将来在应用程序中对独立部分进行建模的正确抽象,因为硬件本身越来越分散,而actor只捕获了它的本质.正如我上面提到的那样,我确实看到了静态打字方面的改进空间.
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |