«Unbox» универсальный тип дискриминационного союза / Поиск хорошего обходного пути - PullRequest
0 голосов
/ 30 октября 2011

Для небольшого синтаксического анализатора AST у меня есть небольшой дискриминируемый союз

type Numerical =
    | Int of int
    | Real of float

для использования в некоторых других конструкциях, таких как

type Vector = Numerical list
Vector [Int 42; Real 13.5]

Когда у меня есть такой метод

let eval (e:Numerical) =
    match e with
    | Int n -> ... (* return int *)
    | Real r -> ... (* return float *)

Я знаю, что F # выводит тип int и выдает ошибку с шаблоном Real во второй строке, поэтому я хочу знать, какой дизайн кода был бы лучшим, чтобы иметь возможностьобрабатывать такие «универсальные» типы и возвращать их соответствующие значения с данными типами.

РЕДАКТИРОВАТЬ

У меня есть ситуация либо *, либо , которая приводитдля таких функций, как

let getInt = function
| Int n -> n
| Real _ -> failwith "Given value doesn't represent an int"

let getReal = function
| Real n -> n
| Int _ -> failwith "Given value doesn't represent a real number"

, однако я хотел бы, чтобы метод, который инкапсулирует оба случая и "автоматически выбирает правильный".

Все это должно привести к возможности реальновыполнять вычисления с «коробочными» значениями, такими как Int 42 и Real 13. с примитивными типами данных, но чтобы иметь возможность вернуть соответствующую оболочку.Если я хочу добавить Real 1. и Real 1.5, я хочу извлечь 1.0 + 1.5 = 2.5, а затем продолжить с Real 2.5, однако я не хочу обрабатывать все как числа с плавающей точкой, чтобы у меня было различие между целыми числами и числами с плавающей точкой.

Ответы [ 2 ]

3 голосов
/ 30 октября 2011

Вы можете привести результаты к obj:

let eval (e:Numerical) =
    match e with
    | Int n -> n :> obj
    | Real r -> r :> obj

Но это, вероятно, не то, что вы хотите.

Другим вариантом будет реализация ваших собственных операций на Numerical:

let (+) a b =
    match (a,b) with
    | (Int an, Int bn) -> Int (an + bn)
    | (Real ar, Real br) -> Real (ar + br)
    | _ -> failwith "Can't add Int and Real"

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

0 голосов
/ 31 октября 2011
let eval<'T> (e:Numerical):'T =
    match e with
    | Int n -> n :> obj :?> 'T
    | Real r -> r :> obj :?> 'T

DEMO

> eval<float>(Real 4.5);;
val it : float = 4.5
> eval<int>(Int 42);;
val it : int = 42
> let x:float = eval (Real 5.5);;
val x : float = 5.5
> let x:int = eval (Real 5.5);;//NG typemismatch
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...