F#: Span, Raise и нижний тип (или их отсутствие)

После того, как я разместил этот комментарий 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

Его ИЖ выглядит намного проще, чем мой оригинальный вариант

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, сначала кажется, что присвоение строкового значения решает эту проблему.

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"

господи, это было мое слепое пятно...

nodakai 17.05.2022 21:09

О, я вижу, что inref не имеет к этому никакого отношения. Я отредактирую свой ответ.

chadnt 17.05.2022 21:22

Другие вопросы по теме