.net F#:跨度、凸起和底部类型(或无)

ehxuflar  于 2023-03-04  发布在  .NET
关注(0)|答案(1)|浏览(100)

在我发表这篇评论之后,我仍然觉得我错过了...https://github.com/fsharp/fslang-suggestions/issues/349#issuecomment-1124206512 I'm still feeling I'm missing out...
为方便读者,此处复制了示例代码:

let spanOfOptString(os: Option<string>) =
  match os with Some(s) -> s.AsSpan()
                | None -> raise(Exception())

错误FS0412:类型示例化涉及byref类型。通用IL的规则不允许这样做。
因此,F#将一个无返回函数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的东西对 * 所有 * byref类型都可用?(我不认为我曾经使用过除(ReadOnlySpan/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看起来比我原来的版本简单多了

更新#2

这基本上与https://github.com/fsharp/fslang-suggestions/issues/872问题相同,后者源于2018年提交的https://github.com/dotnet/fsharp/issues/5776,在发布支持Span的F#4.5后不久

qkf9rpyu

qkf9rpyu1#

它看起来像分配字符串值第一似乎解决它。

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"

相关问题