После того, как я разместил этот комментарий https://github.com/fsharp/fslang-suggestions/issues/349#issuecomment-1124206512 Я все еще чувствую, что упускаю...
Пример кода воспроизведен здесь для удобства читателя:
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# вводит невозвратную функцию raise
как Exception -> 'a
со свободным 'a
(«способ OCaml»), а переменная типа оказалась привязанной к типу по ссылке 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 все? (Я не думаю, что когда-либо использовал какие-либо другие типы byref, кроме (ReadOnly
)Span
/Memory
, но это уже другая история)
Хотя основная команда 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
Его ИЖ выглядит намного проще, чем мой оригинальный вариант
Похоже, сначала кажется, что присвоение строкового значения решает эту проблему.
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
В ФСИ:
> (checkedSpanOfString (Some "foo")).ToString();;
val it: string = "foo"
О, я вижу, что inref
не имеет к этому никакого отношения. Я отредактирую свой ответ.
господи, это было мое слепое пятно...