f# - 为什么 None 在 F# 中自动更改为 null
问题描述
在 F# 交互中尝试以下代码时
> let a = None
- let b = (a, Some 1);;
> b;;
val it : 'a option * int option = (null, Some 1)
它表明 b 具有类型'a option * int option, b 的类型是正确的。但是,元组的第一个元素的值为null,而不是None,为什么?
当尝试验证元组的第一个元素是否真的为空时
printfn "%s" (match b with (null, _) -> "null" | _ -> "not null");;
它给出了以下错误
错误 FS0043:类型“a option”没有“null”作为正确的值
当尝试获取元组中的第一个值时,
let c = fst b;;
它给
错误 FS0030:值限制。值“c”已被推断为具有通用类型 val c : '_a option添加类型注释。
解决方案
该值的内部表示None
确实是一个null
值。但这是内部表示,编译器将null
和识别None
为两个完全不同的值,因此您无法比较它们,因为它们是不同的类型。这就是为什么你得到:error FS0043
。
这其实是需要注意的:
let a = None
let b = (a, Some 1)
let print v = printfn "%A" v
sprintf "%A" a |> print // "<null>"
sprintf "%A" b |> print // "(None, Some 1)"
sprintf "%O" a |> print // "<null>"
sprintf "%O" b |> print // "(, Some(1))"
string a |> print // ""
string b |> print // "(, Some(1))"
a .IsNone |> print // true
a .IsSome |> print // false
a .GetType() |> print // System.NullReferenceException: Object reference not set to an instance of an object.
a .ToString() |> print // System.NullReferenceException: Object reference not set to an instance of an object.
(fst b).ToString() |> print // System.NullReferenceException: Object reference not set to an instance of an object.
(snd b).ToString() |> print // "Some(1)"
...因为在值上调用某些方法None
会引发可怕的NullReference
异常并且转换为字符串也是不稳定的。
关于error FS0030
基本上值不能是通用的。这已在 SO 中多次讨论。
来自可区分联合的值似乎以特殊方式处理,它们似乎被授予例外,例如这些是通用的并且仍然可以:
type MyDU<'A, 'B> =
| ValNo
| ValA of 'A
| ValB of 'B
let v1 = ValNo // MyDU<'a,'b> double generic but Ok
let v2 = ValA 1 // MyDU<int,'a> generic but Ok
let v3 = ValB 1 // MyDU<'a,int> generic but Ok
但这些都不好
let valNo() = ValNo
let valA a = ValA a
let valB b = ValB b
let w1 = valNo() // MyDU<'_a,'_b> double generic not Ok
let w2 = valA 1 // MyDU<int,'_a> generic not Ok
let w3 = valB 1 // MyDU<'_a,int> generic not Ok
推荐阅读
- angular - 无法在事件预览中显示操作按钮。¿ 我忘记了什么?
- java - 我想计算我在测验应用程序中提交的每个正确和错误答案,并希望在 textview 中显示分数
- php - Yajra Datatables HTML Builder,请求的未知参数
- mysql - mysql docker容器 - 无法与Windows连接
- c++ - 如何使用模板将char作为类内函数的参数传递
- javascript - 如何修复 NPM 高危漏洞?(污染)
- javascript - 如何使用 discord.js 12.5.3 获取成员的所有用户名
- google-apps-script - 参数 (DocumentApp.ListItem) 与 DocumentApp.Body.appendParagraph 的方法签名不匹配
- css - 在 CSS 中生成文本动画循环
- python - 我将如何在这里实现回溯?