Размеченная проверка типа объединения в F# с разными возвращаемыми типами

Я пытаюсь написать интерпретатор на F#. Я хочу проверить тип выражений.

Вот мой размеченный союз для выражений

type Expr =
| Integer of int
| String of string
| Boolean of bool

Это метод, который я использую для проверки типов с помощью

let checkType (e:Expr) =
match e with 
| String s -> s
| Integer i -> i
| Boolean b -> b

Я хочу, чтобы метод определял, является ли выражение строкой, целым числом или логическим значением.

Однако Visual Studio дает мне следующую ошибку в строке 4 метода checkType:

 This expression was expected to have type string but here has type int

Я что-то упускаю?


comment
Текущая ошибка связана с тем, что функция может возвращать выражение только одного типа.   -  person John Palmer    schedule 18.04.2016


Ответы (2)


Чтобы расширить комментарий Джона Палмера:

F# предполагает, что каждая функция будет иметь один возвращаемый тип. Например, вы можете написать функцию, которая принимает целое число и возвращает целое число, что будет функцией типа int -> int. Функция, которая анализирует строки в целые числа, будет иметь тип string -> int. И так далее.

Итак, каков тип возвращаемого значения функции checkType, которую вы написали? Поскольку вы не указываете возвращаемый тип, компилятор смотрит на тип значений, которые вы можете вернуть из функции — каждая возможная ветвь кода должна возвращать значение, и все они должны быть одного типа. Итак, он просматривает ваш оператор match, видит, что его первая ветвь возвращает string, и говорит: «Ага! Я вычислил тип возвращаемого значения этой функции; это функция, которая принимает Expr и возвращает строку. тип функции Expr -> string."

Затем он просматривает вторую ветвь вашего оператора match и говорит: «Подождите минутку. Это функция, которая возвращает string, но в этой ветке кода она возвращает int. Это недопустимо: код, вызывающий эту функцию, требует чтобы знать, какой тип ожидать, что он вернется." И поэтому вы получаете ошибку.

Теперь, если бы вы поменяли местами порядок ваших match операторов, проверяя сначала Integer i, тогда компилятор оценил бы вашу функцию как имеющую тип Expr -> int (принимая входные данные Expr и возвращающие выходные данные int), и выдал бы ошибку на | String s -> s линия. На этот раз ошибка будет такой: «Подождите, это функция, которая возвращает int, поэтому выражение s здесь должно было иметь тип int. Но вместо этого оно имеет тип string. Это недопустимо».

Или удалите строку | String s -> s, и вы увидите сообщение об ошибке «Это выражение должно было иметь тип int, но здесь имеет тип bool». То же самое: каждая функция может иметь только один тип возвращаемого значения. Если вы хотите вернуть из функции несколько разных возможных типов, для этого и нужны размеченные объединения.

Дополнительные сведения о типах F# см. в разделе http://fsharpforfunandprofit.com/series/understanding-fsharp-types.html< /а>.

person rmunn    schedule 18.04.2016

Вы можете обернуть все выражения в тип Option, например Some или String:

let checkType (e:Expr) =
    match e with
    | String e -> "we are string: " + string e
    | Integer e-> "we are integer: " + string e
    | Boolean e -> "we are boolean: " + string e
person s952163    schedule 18.04.2016