F#:使用区分联合解构绑定
Posted
技术标签:
【中文标题】F#:使用区分联合解构绑定【英文标题】:F#: Destructuring bind with a discriminated union 【发布时间】:2016-07-14 01:50:57 【问题描述】:open System
let x = (1, 2)
let (p, q) = x
printfn "A %A" x
printfn "B %A %A" p q
let y = Some(1, 2)
try
let None = y
()
with
| ex -> printfn "C %A" ex
let Some(r, s) = y
printfn "D %A" y
// printfn "E %A %A" r s
http://ideone.com/cS9bK0
当我取消注释最后一行时,编译器会拒绝抱怨的代码
/home/rRiy1O/prog.fs(16,19):错误 FS0039:未定义值或构造函数“r” /home/rRiy1O/prog.fs(16,21): error FS0039: The value or constructor's' is not defined
在解构let
时不允许使用枚举吗?
但首先,即使我注释掉最后一行......我在这里做什么 am?这是输出:
A (1, 2)
B 1 2
D Some (1, 2)
更新
为了记录,这里是固定版本:
open System
let x = (1, 2)
let (p, q) = x
printfn "A %A" x
printfn "B %A %A" p q
let y = Some(1, 2)
try
let (None) = y
()
with
| ex -> printfn "C %A" ex
let (Some(r, s)) = y
printfn "D %A" y
printfn "E %A %A" r s
http://ideone.com/7qL9mH
输出:
A (1, 2)
B 1 2
C MatchFailureException ("/home/MBO542/prog.fs",10,6)
D Some (1, 2)
E 1 2
完美。
【问题讨论】:
没有直接关系,但let None = y
行是否创建了一个名为 None 的新值?
@MarkPattison \(^o^)/
在 F# 中,应该避免重新定义 None
或 Some
,但现在看来,您正在以一种艰难的方式学习这一点。同样对于 .NET 和 F#,尤其要避免使用 try ... catch
,因为它在时间上很昂贵。如果您需要捕获错误/异常,强烈考虑使用Option type 或更高级的场景Railway oriented programming
你能改一下标题吗,我没有看到枚举。
@GuyCoder 傻了我,我更新了标题。有区别的联合在 Rust 中被称为枚举,我花了很多时间。顺便说一句,try...catch
专门用于针对None
的非详尽模式匹配,这会产生异常(我在移动设备上,找不到它的确切名称。)我的意图不是重新定义None
。您似乎误解了我提出这个问题的意图。
【参考方案1】:
你尝试解构y
的方式:
let Some(r, s) = y
您实际上是在定义一个名为Some
的函数,它有两个参数r
和s
,以元组形式传递。
为了正确解构,需要加括号:
let (Some (r, s)) = y
顺便说一句,try
块内也发生了同样的事情:let None = y
行创建了一个名为 None
的新值,等于 y
。
【讨论】:
Option
枚举的两种情况都编译得很好,但与我的意图背道而驰,这一事实让我非常沮丧。顺便问一下,您是如何获得这些知识的?根据经验,还是我错过了语言参考中的任何描述?
经验为王,当然。没有什么比实际用它做某事更能让人理解事物了。向他人解释也有助于提高你自己的理解,这就是我在这里的原因:-)。除此之外,我一直推荐优秀资源fsharpforfunandprofit.com,里面有各种精彩的解释。
使用 VS(或者可能是其他 IDE)可以很容易地看到发生了什么,通过将鼠标悬停在事物上来查看它们的隐含类型。否则交互窗口会立即报告类型。
@MarkPattison 真的,要是我家里的 Linux PC 上有 VS 就好了 :-)
在 Linux 上,试试 Visual Studio Code + Ionide 插件 for F#以上是关于F#:使用区分联合解构绑定的主要内容,如果未能解决你的问题,请参考以下文章
为啥 F# 可区分联合无法使其 TypeConverter 受到 JSON.NET 的尊重,而其他类型却可以?