F#:跨度、提升和底部类型(或缺少)
F#: Span, raise, and the bottom type (or lack thereof)
在我发表这条评论后https://github.com/fsharp/fslang-suggestions/issues/349#issuecomment-1124206512
我仍然觉得我错过了...
为了 reader 的方便,此处复制了示例代码:
let spanOfOptString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception())
error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
因此,F# 将无 return 函数 raise
键入为 Exception -> 'a
并使用自由 'a
(“OCaml 方式”),并且类型变量发生了绑定到 byref 类型 ReadOnlySpan
,这是非法的。我觉得我因为我没有犯下的罪行而受到惩罚......
我可以找到类似
的解决方法
let checkedSpanOfString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception()) // 'a = unit
ReadOnlySpan.Empty // both arms: ReadOnlySpan<char>
https://sharplab.io/#gist:32b520574fde97de8d7389ab04f64bc4
但是恕我直言,这有点难看。而且我不认为我们应该期待 .Empty
等同于 all byref 类型的东西? (我不认为我曾经使用过除 (ReadOnly
)Span
/Memory
之外的任何其他 byref 类型,但这是另一回事)
虽然 F# 核心团队似乎并没有打算将底层类型引入语言(这可能是一个明智的工程决策),
有人有更好的替代方法来完成这项工作吗?
更新
@chadnt 的回答可以内联得到
let checkedSpanOfString(os: Option<string>) =
let s = match os with Some(s) -> s
| None -> raise(Exception())
s.AsSpan()
https://sharplab.io/#gist:a5eab805c539c45048b4072fa7b096c5
它的IL看起来比我原来的版本简单多了
看来先给字符串赋值似乎就解决了。
open System
let valueOrRaise = function
| Some v -> v
| None -> raise(Exception())
let checkedSpanOfString (os: string option) =
let s = valueOrRaise os
s.AsSpan()
https://sharplab.io/#gist:2ca959f498be87f1b52212182af237b4
在 FSI 中:
> (checkedSpanOfString (Some "foo")).ToString();;
val it: string = "foo"
在我发表这条评论后https://github.com/fsharp/fslang-suggestions/issues/349#issuecomment-1124206512 我仍然觉得我错过了...
为了 reader 的方便,此处复制了示例代码:
let spanOfOptString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception())
error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
因此,F# 将无 return 函数 raise
键入为 Exception -> 'a
并使用自由 'a
(“OCaml 方式”),并且类型变量发生了绑定到 byref 类型 ReadOnlySpan
,这是非法的。我觉得我因为我没有犯下的罪行而受到惩罚......
我可以找到类似
的解决方法let checkedSpanOfString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception()) // 'a = unit
ReadOnlySpan.Empty // both arms: ReadOnlySpan<char>
https://sharplab.io/#gist:32b520574fde97de8d7389ab04f64bc4
但是恕我直言,这有点难看。而且我不认为我们应该期待 .Empty
等同于 all byref 类型的东西? (我不认为我曾经使用过除 (ReadOnly
)Span
/Memory
之外的任何其他 byref 类型,但这是另一回事)
虽然 F# 核心团队似乎并没有打算将底层类型引入语言(这可能是一个明智的工程决策),
有人有更好的替代方法来完成这项工作吗?
更新
@chadnt 的回答可以内联得到
let checkedSpanOfString(os: Option<string>) =
let s = match os with Some(s) -> s
| None -> raise(Exception())
s.AsSpan()
https://sharplab.io/#gist:a5eab805c539c45048b4072fa7b096c5
它的IL看起来比我原来的版本简单多了
看来先给字符串赋值似乎就解决了。
open System
let valueOrRaise = function
| Some v -> v
| None -> raise(Exception())
let checkedSpanOfString (os: string option) =
let s = valueOrRaise os
s.AsSpan()
https://sharplab.io/#gist:2ca959f498be87f1b52212182af237b4
在 FSI 中:
> (checkedSpanOfString (Some "foo")).ToString();;
val it: string = "foo"