Может ли ограничение универсального типа F# указывать более 1 допустимого типа?

У меня есть эта примерная подпись функции:

let func1 (input:'a when 'a :> (IReadOnlyDictionary<string, string>)) =
...

Я также хотел бы разрешить 'a быть IDictionary<string, string>). Таким образом, любой тип может быть передан. Код, использующий параметр input, вызывает TryGetValue, который поддерживают оба интерфейса.

Можно ли указать ограничение типа ИЛИ, подобное этому? Если да, то каков конкретный синтаксис для этого?

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
4
0
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я почти уверен, что вы не можете, но вы можете использовать SRTP, чтобы запросить метод TryGetValue:

let inline func1 (input : 'a when 'a : (member TryGetValue : string * byref<string> -> bool)) =
    let mutable value = ""
    let flag = input.TryGetValue("key", &value)
    flag, value

Это некрасиво, но это работает. Здесь это называется с помощью IDictionary:

dict [ "key", "value" ]
    |> func1
    |> printfn "%A"   // (true, "value")

И здесь это называется IReadOnlyDictionary:

dict [ "key", "value" ]
    |> System.Collections.ObjectModel.ReadOnlyDictionary
    :> System.Collections.Generic.IReadOnlyDictionary<_, _>
    |> func1
    |> printfn "%A"   // (true, "value")

Действительно. Можно написать let func1 (input: 'a when 'a :> (IReadOnlyDictionary<string,string>) and 'a :> (IDictionary<string,string>)) =, но это не сработает, потому что два интерфейса не реализованы одновременно, даже для System.Collections.Generic.Dictionary<_,_>. И не допускается дизъюнкция в ограничениях типа. Таким образом, выбор нужных элементов, как показано выше, должен работать. И вы можете использовать конструкцию and для объединения нескольких таких ограничений членов.

jpe 30.12.2022 07:57

@brian-berns Это сработало отлично! Я был рад узнать, как указать ограничение для метода TryGetValue. Я пытался, но не мог понять часть значения out. Я определенно забрел в глубокий конец с этим. Я заметил, что в F# методы типа Try из .NET framework автоматически переписываются или перекомпилируются для возврата кортежа bool * T вместо использования метода out value. Я предполагаю, что компилятор не будет знать о таком случае, поэтому интересно узнать, что F# может выдавать значения, когда это необходимо.

Matthew MacFarland 02.01.2023 15:22

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