Очень часто при написании общего кода в F # Я прихожу в ситуации, подобной этой (я знаю, что это малоэффективным, только для демонстрационных целей):Как я могу вернуть обратно тип, который был ранее?
let isPrime n =
let sq = n |> float |> sqrt |> int
{2..sq} |> Seq.forall (fun d -> n % d <> 0)
Для многих задач можно использовать statically resolved types и получить даже повышение производительности из-за inlining.
let inline isPrime (n:^a) =
let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
let sq = n |> float |> sqrt |> int
{two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
Код, указанный выше, не будет скомпилирован из-за того, что верхний предел последовательности является поплавком. В некотором роде, я мог бы просто вернуться к int
, например.
Но компилятор не позволит мне использовать любой из них:
let sq = n |> float |> sqrt :> ^a
let sq = n |> float |> sqrt :?> ^a
и эти два приводят к InvalidCastException
:
let sq = n |> float |> sqrt |> box |> :?> ^a
let sq = n |> float |> sqrt |> box |> unbox
Кроме того, upcast
и downcast
запрещены.
let sq = System.Convert.ChangeType(n |> float |> sqrt, n.GetType()) :?> ^a
работает, но мне кажется очень громоздким.
Есть ли способ, которым я пропустил или мне действительно нужно использовать последнюю версию? Потому что последний будет разбит на bigint
, что мне нужно довольно часто.
Я немного поработал, и самое приятное решение, с которым я столкнулся, состояло в том, чтобы изменить основную библиотеку. Если вы не особенно заботитесь о производительности, вы всегда можете создать число, добавив полномочия двух. –
Зачем вам нужно вводить 'float' перед вызовом' sqrt'? – Daniel
@ Даниэль, потому что вы не можете (например) передать int в sqrt: 'Тип 'int' не поддерживает оператор 'Sqrt'' – phoog