F# - 类型参数不能用作类型构造函数
F# - Type parameter cannot be used as type constructor
我在 F# 中与 Akkling 一起工作,因此我可以在 Akka.net 上使用强类型的 actor,但我在 F# 中遇到了设计限制,我想知道是否有一种优雅的方法来解决这个问题。
以我的根消息类型为例,我真的不想在那里有 IActorRef<_>,因为这种类型将存在于一个公共库中,不应该知道它使用的消息系统。此外,为了便于测试,我不想创建整个演员系统(或测试套件)。
type MessageType =
| World of WorldMessage
| Location of IActorRef<LocationMessage> * LocationMessage
| Client of IActorRef<LocationMessage> * ClientMessage
一个糟糕的解决方法是:
type MessageType<'LocationActor, 'PlayerActor, 'ClientActor> =
| World of WorldMessage<'ClientActor>
| Location of 'LocationActor * LocationMessage<'ClientActor>
| Client of 'ClientActor * ClientMessage<'LocationActor>
理想情况下,我想要这个但是存在语言限制(错误:类型参数不能用作类型构造函数):
type MessageType<'a> =
| World of WorldMessage<'a>
| Location of 'a<LocationMessage> * LocationMessage
| Client of 'a<LocationMessage> * ClientMessage
评论中已经提到了实际的类型系统问题(缺少 HKT),但我认为它们对于解决这里的设计问题并不是真正必要的。
您不希望直接依赖于 Akka.NET,但您仍然希望您的类型带有一个概念,即让 actor 引用与消息一起使用。一种解决方法是围绕 Actors 引入您自己的界面(作为实际界面类型或一组函数,具体取决于您的上下文中的意义)。
因此,在您的公共图书馆中,您拥有自己的 IMyActorRef
以及您认为合理的 IActorRef
功能的公共子集:
type IMyActorRef<'msg> =
abstract member Tell: ... -> ...
abstract member Ask: ... -> ...
并根据该接口定义您的消息类型(以及使用它的实际逻辑):
type MessageType =
| World of WorldMessage
| Location of IMyActorRef<LocationMessage> * LocationMessage
| Client of IMyActorRef<ClientMessage> * ClientMessage
然后在您引用 Akka.NET 的地方提供它的实现。
我在 F# 中与 Akkling 一起工作,因此我可以在 Akka.net 上使用强类型的 actor,但我在 F# 中遇到了设计限制,我想知道是否有一种优雅的方法来解决这个问题。
以我的根消息类型为例,我真的不想在那里有 IActorRef<_>,因为这种类型将存在于一个公共库中,不应该知道它使用的消息系统。此外,为了便于测试,我不想创建整个演员系统(或测试套件)。
type MessageType =
| World of WorldMessage
| Location of IActorRef<LocationMessage> * LocationMessage
| Client of IActorRef<LocationMessage> * ClientMessage
一个糟糕的解决方法是:
type MessageType<'LocationActor, 'PlayerActor, 'ClientActor> =
| World of WorldMessage<'ClientActor>
| Location of 'LocationActor * LocationMessage<'ClientActor>
| Client of 'ClientActor * ClientMessage<'LocationActor>
理想情况下,我想要这个但是存在语言限制(错误:类型参数不能用作类型构造函数):
type MessageType<'a> =
| World of WorldMessage<'a>
| Location of 'a<LocationMessage> * LocationMessage
| Client of 'a<LocationMessage> * ClientMessage
评论中已经提到了实际的类型系统问题(缺少 HKT),但我认为它们对于解决这里的设计问题并不是真正必要的。
您不希望直接依赖于 Akka.NET,但您仍然希望您的类型带有一个概念,即让 actor 引用与消息一起使用。一种解决方法是围绕 Actors 引入您自己的界面(作为实际界面类型或一组函数,具体取决于您的上下文中的意义)。
因此,在您的公共图书馆中,您拥有自己的 IMyActorRef
以及您认为合理的 IActorRef
功能的公共子集:
type IMyActorRef<'msg> =
abstract member Tell: ... -> ...
abstract member Ask: ... -> ...
并根据该接口定义您的消息类型(以及使用它的实际逻辑):
type MessageType =
| World of WorldMessage
| Location of IMyActorRef<LocationMessage> * LocationMessage
| Client of IMyActorRef<ClientMessage> * ClientMessage
然后在您引用 Akka.NET 的地方提供它的实现。