MYTYPE типа? - PullRequest
       7

MYTYPE типа?

1 голос
/ 27 апреля 2020

У меня есть объявление типа

type MYVAL = INT of int

и я хочу выполнить арифметические c операции над константами и переменными типа MYVAL, например

let a : MYVAL = 10
let b : MYVAL = 25
let c = a+b

Однако, когда я запустить его, он утверждает, что MYVAL не поддерживает оператор +. Разве MYVAL не рассматривается как целочисленный тип? Если это не так, что делает INT of int? Как бы вы выполняли арифметические c операции с переменными и константами типа MYVAL?

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

MYVAL не рассматривается как целочисленный тип. Если это то, что вы хотите, вы можете использовать сокращение типа; type MYVAL = int. Я не уверен, почему вы хотели бы сделать это, но это определенно возможно.

В вашем текущем определении, MYVAL - это объединенный в один случай союз. Он переносит данный тип, но не наследует ни один из операторов базового типа. Кстати, способ создания INT - это let a = INT 10, а не let a : MYINT = 10.

. Если вы хотите, вы можете реализовать свой собственный оператор сложения, например

type MYVAL = INT of int with
    static member (+) (INT a, INT b) = INT(a+b)

, который позволит вам сделать

let a = INT 10
let b = INT 25
let c = a+b

Это необходимо сделать для любого оператора, которого вы хотите использовать, например, (-), (*), et c.

* 1020. * Это может показаться немного запутанным, я имею в виду , почему мы не хотим, чтобы операторы генерировались автоматически? Что ж, если вы пишете парсер, вы можете захотеть прочитать int или string. Такой парсер может вывести значение типа type MYVAL = INT of int | STRING of string. Как тогда будет определяться (+)? Как насчет (-)?

В примере с синтаксическим анализатором MYVAL больше не будет единичным распознаваемым объединением, так как оно имеет несколько случаев. Естественный вопрос: почему тогда интересны профсоюзы с единичными случаями? Кто хотел бы использовать что-нибудь подобное? Оказывается, это довольно аккуратно для подтипирования. Допустим, вы хотите представить число, которое больше 10. Один из способов сделать это -

type HigherThan10 = private Value of int with
    static member TryCreate(x: int) =
        if x >= 10
        then Some(Value(x))
        else None

let x = Value(1) // Error
let y = HigherThan10.TryCreate(1) // None
let z = HigherThan10.TryCreate(10) // Some

Я знаю, что это не самый интересный пример, но его можно использовать для представления адреса электронной почты в качестве подтипа. из string. Кстати, обратите внимание, как это позволяет избежать использования исключений для потока управления, возвращая HigerThan10 option.

1 голос
/ 27 апреля 2020

Причина, по которой простая сумма не работает, уже была объяснена. Я просто покажу другой вариант: вы можете определить функцию map2 для вашего типа:

type MYVAL =
    | INT of int
    static member map2 f (INT x) (INT y) = INT (f x y)

//This is the correct way to initialize MYVAL, since it is a single-case discriminated union
let a = INT 10
let b = INT 25

//sum
MYVAL.map2 (+) a b   //INT 35

//mult
MYVAL.map2 (*) a b   //INT 250

//mod
MYVAL.map2 (%) a b   //INT 5
...