Тип теста дает ошибку для объединения тест-выражения - PullRequest
1 голос
/ 11 марта 2020

Мой вопрос относится к следующей программе.

open System

// Types
type Car (brand: string) =
    member _.Brand = brand
type BMW () =
    inherit Car "BMW"
type Pet =
    | Cat
    | Dog

[<EntryPoint>]
let main argv =
    // Match subtype of test-expression type: ok
    let car = Car "Mercedes"
    let carResult =
        match car with
        | :? BMW -> 1
        | _ -> 0
    // Match type of test-expression: "will always hold" warning
    let bmw = BMW ()
    let bmwResult =
        match bmw with
        | :? BMW -> 1
        | _ -> 0
    // Catch any exception: "will always hold" warning
    let exceptionResult =
        try
            1/0
        with
            | :? Exception -> 2
    // Match type of test-expression (union type): "The type 'Pet' does not have any proper subtypes" error
    let cat = Cat // this has type Pet
    let catResult =
        match cat with
        | :? Pet -> 1
        | _ -> 0
    0

В первом тесте выражение-выражение имеет тип Car, из которых тип в шаблоне проверки типа, BMW, является подтипом, и нет никаких предупреждений или ошибок. Во втором и третьем тестах тип в тестовом шаблоне типа совпадает с типом тестового выражения, и по понятным причинам возникает предупреждение, потому что когда программист проверяет, действительно ли BMW является BMW или Exception на самом деле Exception, это, вероятно, логическая ошибка.

Последний тест имеет ту же форму, что и тесты два и три: выражение-тест имеет тип Pet и типовой тестовый шаблон также Pet. Так почему в этом случае он генерирует ошибку? Ошибка говорит The type 'Pet' does not have any proper subtypes.... Но BMW не имеет подтипов и не дает этой ошибки. Более того, на странице Сопоставление с образцом (в разделе «Шаблон проверки типа») говорится, что «Если тип ввода соответствует (или является производным типом) типу, указанному в образце, сопоставление завершается успешно». Pet соответствует Pet, er go, et c .. Почему тип объединения обрабатывается по-разному?

1 Ответ

2 голосов
/ 11 марта 2020

Возможно, сообщение об ошибке сформулировано слишком расплывчато. Дело не в том, что тип Pet не имеет подтипы, а в том, что он не может иметь подтипы.

Поскольку BMW является классом, он может иметь подтип из другой сборки, который был скомпилирован после того, где определен сам BMW.

Но для Pet этого не может быть, потому что типы сумм не могут иметь подтипов, и поэтому сопоставление наследования для этих типов запрещено.

Также обратите внимание, что источником ошибки является тип переменной, которая соответствует, а не тип шаблона. Так, например, это скомпилируется без ошибок:

let n : obj = null

match n with
| :? Pet -> "is a pet"
| _ -> "no idea"

Это работает, потому что n имеет тип obj, который имеет , имеет подтипы, из которых Pet это один (это. NET в конце концов, все является объектом). Но сопоставление с вашей переменной cat не работает, потому что эта переменная имеет тип, не имеющий подтипов.

...