首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回Union类型而非Union Case

返回Union类型而非Union Case
EN

Stack Overflow用户
提问于 2021-02-16 05:26:41
回答 1查看 41关注 0票数 0

我有一个像这样的联合类型

代码语言:javascript
复制
  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类型:

代码语言:javascript
复制
 type RegisteredAccount = {
      Owner: string
      Balance: decimal
      AccountId: Guid }
  
  type Account =
    | Unregistered
    | Registered of RegisteredAccount

有一个函数evolve

代码语言:javascript
复制
  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

代码语言:javascript
复制
let build = List.fold evolve
let rebuild = build Unregistered

如果我没有显式地将evolve的返回类型指定为Account,则let build = List.fold evolve行将出现以下错误

代码语言:javascript
复制
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错误。

代码语言:javascript
复制
This expression was expected to have type 'Account' but here has type 'RegisteredAccount'

我该如何解决这个问题呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-16 06:17:15

我认为您代码中的问题是evolve函数试图返回RegisteredAccount记录类型的值,而不是Account联合类型的值。

我看到您希望使用Unregistered值(类型为Account)作为初始值,并且还添加了一个类型注释,指定evolve的返回类型应为Account。我想这就是你想要的。唯一缺少的是,您需要使用Registered联合用例包装返回值,以便将RegisteredAccount转换为Account

下面的类型检查对我来说没问题:

代码语言:javascript
复制
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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66215624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档