generics - 试图理解 F# 中的 Choice 类型

标签 generics f# discriminated-union

我一直在努力理解 Scott Wlaschin 的 RoP 文章中的代码:

http://fsharpforfunandprofit.com/posts/railway-oriented-programming-carbonated/

他在 F# 中使用了 Choice1Of2 和 Choice2Of2 类型。当我遇到以下情况时,我试图通过调试来了解如何利用这些东西:

module TestModule
open Microsoft.VisualStudio.TestTools.UnitTesting

// generic union type (like Choice1Of2, I think)
type Things<'a> =
    | Thing of 'a

// explicit union type (for comparison)
type Numbers =   
    | Integer of int

[<TestClass>]
type Tests() =

    // method to make a Choice1Of2 (from the article)
    let makeChoice (a : string) : Choice<string, 'a> = 
        Choice1Of2 a

    [<TestMethod>]
    member public this.WhyYouNoHaveItemValueAndStuff() =      
        let choice1 = Thing "test"          // debug = Thing "this"
        let choice2 = Integer 3             // debug = Integer 3
        let choice3 = makeChoice "test"     // debug = Choice1Of2 w/Item = "test"
        let choice4 = Choice1Of2 "test"     // debug = Tests.choice4@24 ???

        // bogus test stuff below here
        let choices = (choice1, choice2, choice3, choice4)
        Assert.IsNotNull(choices)

为什么当我直接做一个Choice1Of2(choice4)时,我得到的调试结果不是和choice 3一样。为什么要使用一个方法来做choice3才能得到和choice1&2一样的结果?

编辑:

似乎将选择4更改为:
let choice4 : Choice<string, Object> = Choice1Of2 "test" 

解决这个问题。我完全不清楚为什么我需要它。任务的右侧对正在设置的类型一清二楚。

最佳答案

Choice类型的定义如下

 type Choice<'a, 'b> =
      | Choice1Of2 of 'a
      | Choice2Of2 of 'b

因此,当您像在 choice4 中所做的那样构造 Choice 类型的实例时你只使用这些支腿之一,这基本上会留下一个洞(描述 'b 的类型)调试器必须填充,实际上在运行时它甚至不能确定类型实际上是 Choice<'a,'b>所以你会得到一些由 FSharpFunc 表示的临时类型。与类型推断机制将报告 Choice<string, 'a> 的方式大致相同哪里'a表示孔,直到匹配实例,然后强制您键入另一侧。提供内联类型签名,例如
 let choice4 : Choice<string, bool> = Choice1Of2 "test"

意味着您正在填补漏洞并为调试器提供足够的信息来正确表示类型。

编辑(见评论):choice3 表示为 Choice1Of2<string,obj>因为 obj被认为是顶部(最通用的类​​型)。这是在耗尽所有其他选项时使用的类型推断机制回退类型。如果我们添加一些代码,例如
let result =
    match choice3 with
    | Choice1Of2 t -> t.GetHashCode()
    | Choice2Of2 t -> t  

那么我们会得到Choice<string, int>作为GetHashCode()的类型是 int因此第二个匹配子句的结果必须是 int对于结果的类型,让表达式保持一致。

关于generics - 试图理解 F# 中的 Choice 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28115431/

相关文章:

f# - 如何解决联合案例之间的循环引用?

asynchronous - F# 异步和匿名函数

TypeScript - 根据鉴别器将联合类型映射到另一个联合类型的函数

generics - Kotlin 是否有等效于 C#'s "default"的关键字?

Java 泛型 : Wildcard capture misunderstanding

c# - 使用 Wrapped<B> 类填充 Wrapped<A> 的集合,其中 B 实现 A

generics - Kotlin的全局通用值(value)

f# - if 需要 else 子句

f# - 使用列表中的 Discriminated union 测试相等性

c++ - 关于 C++ 非 POD union 的问题