我有一个像这样的联合类型
type AccountCreated =
{ Owner: string
AccountId: Guid
CreatedAt: DateTimeOffset
StartingBalance: decimal }
type AccountDebited =
{ To: Guid
From: Guid
Description: string
Time: DateTimeOffset
Amount: decimal }
type AccountCredited =
{ To: Guid
From: Guid
Description: string
Time: DateTimeOffset
Amount: decimal }
type AccountEvent =
| Created of AccountCreated
| AccountCredited of AccountCredited
| AccountDebited of AccountDebited和另一个类似的Union类型:
type RegisteredAccount = {
Owner: string
Balance: decimal
AccountId: Guid }
type Account =
| Unregistered
| Registered of RegisteredAccount有一个函数evolve
let evolve state event: Account =
match event with
| Created accountCreated ->
{ AccountId = accountCreated.AccountId
Owner = accountCreated.Owner
Balance = accountCreated.StartingBalance }
| AccountDebited accountDebited ->
match state with
| Registered s ->
{ s with
Balance = s.Balance - accountDebited.Amount }
| _ -> failwith "unregistered account can't be debited"
| _ -> failwith "todo: other cases"应该使用List.fold来使用evolve
let build = List.fold evolve
let rebuild = build Unregistered如果我没有显式地将evolve的返回类型指定为Account,则let build = List.fold evolve行将出现以下错误
Type mismatch. Expecting a 'Account -> AccountEvent -> Account' but given a 'Account -> AccountEvent -> RegisteredAccount' The type 'Account' does not match the type 'RegisteredAccount'如果将返回类型设置为evolve,我在Created的模式匹配中得到编译器错误,在AccountDebited模式匹配中得到一个类似的Registered错误。
This expression was expected to have type 'Account' but here has type 'RegisteredAccount'我该如何解决这个问题呢?
发布于 2021-02-16 06:17:15
我认为您代码中的问题是evolve函数试图返回RegisteredAccount记录类型的值,而不是Account联合类型的值。
我看到您希望使用Unregistered值(类型为Account)作为初始值,并且还添加了一个类型注释,指定evolve的返回类型应为Account。我想这就是你想要的。唯一缺少的是,您需要使用Registered联合用例包装返回值,以便将RegisteredAccount转换为Account。
下面的类型检查对我来说没问题:
let evolve state event: Account =
match event with
| Created accountCreated ->
{ AccountId = accountCreated.AccountId
Owner = accountCreated.Owner
Balance = accountCreated.StartingBalance } |> Registered
| AccountDebited accountDebited ->
match state with
| Registered s ->
{ s with
Balance = s.Balance - accountDebited.Amount } |> Registered
| _ -> failwith "unregistered account can't be debited"
| _ -> failwith "todo: other cases"我所要做的就是在返回记录的两个地方添加|> Registered!
https://stackoverflow.com/questions/66215624
复制相似问题