Типовое ограничение в Дискриминационном Союзе - PullRequest
3 голосов
/ 01 сентября 2009

Считайте, что

type Foo =
  | I of int
  | S of string



let test = [ I(5); I(9); I(7)]

Это работает, но теперь я хочу, чтобы 'test' тоже относился к типу Foo и все еще представлял собой список из I или S. Например.

let test = L( [ I(5); I(9); I(42) ] ) //works!
let test2 = L( [ I(5); I(9); S("stuff") ] ) //type error
let test3 = L( [ I(5); I(9); L([]) ] ) //type error

Я пытаюсь это ..

type Foo =
  | I of int
  | S of string
  | L of 'T list when 'T :> Foo

Я знаю, что это, очевидно, не работает. Мне было просто написать что-то естественное.

Большое спасибо за помощь !!

Ответы [ 4 ]

7 голосов
/ 01 сентября 2009

Вы не можете использовать ограничение общего типа для «различимого объединения». Но вы можете привязать определенный тип к этому Дискриминационному союзу, как показано ниже.

type Foo = 
    | I of int 
    | S of string
    | L of Foo list


// Usage
let test = L( [ I(5); I(9); S("stuff"); L([]); I(42) ] )

Это отвечает на ваш вопрос?

5 голосов
/ 01 сентября 2009

Крис имеет хороший ответ. Если вы не хотите, чтобы списки гнездились, вы также можете сделать

type FooAtom = 
    | I of int 
    | S of string

type Foo = 
    | A of FooAtom
    | L of FooAtom list

let test  = L( [ I(5); I(9); S("stuff"); I(42) ] )
let test2 = A( I(5) )
2 голосов
/ 02 сентября 2009

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

type I = int
type S = string

type Foo =
    | I
    | S
    | LI of I list
    | LS of S list
1 голос
/ 01 сентября 2009

Вы не можете говорить «это список некоторых членов Foo и других (не Foo) вещей» в терминах системы типов F #. Но вы можете использовать время выполнения и еще один уровень косвенности:

type Foo = I of int | S of string

let (|F|L|) (o: obj) =
  match o with
  | :? Foo as v -> F v
  | :? list<Foo> as v -> L v
  | _ -> failwith "unknown type"
;;

let f = function
  | F _ -> "Foo"
  | L _ -> "List of Foos"
;;

List.map f [ box (I 1); box (S "stuff"); box ([I 2; S "foo"]) ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...