Раньше я использовал инструмент с открытым исходным кодом, названный HTMLParser . Он разработан, чтобы анализировать HTML по-разному и хорошо служит цели. Он может анализировать HTML как другой treenode, и вы можете легко использовать его API для получения атрибутов из узла. Проверьте это и посмотрите, поможет ли это вам.
Вы можете иметь частные конструкторы дел, но выставлять публичные активные шаблоны с такими же именами. Вот как вы можете определить и использовать их (функции создания для краткости опущены):
module Helpers =
type ValidValue =
private
| ValidInt of int
| ValidString of string
let (|ValidInt|ValidString|) = function
| ValidValue.ValidInt i -> ValidInt i
| ValidValue.ValidString s -> ValidString s
module Usage =
open Helpers
let validValueToString = function
| ValidInt i -> string i
| ValidString s -> s
//
Если нет особой причины, по которой требуется дискриминационное объединение, учитывая тот конкретный вариант использования, который вы предоставили, это звучит так, как будто вы на самом деле не хотите дискриминационного объединения вообще, поскольку активный шаблон будет более полезным. Например:
let (|ValidInt|ValidString|Invalid|) (value:obj) =
match value with
| :? int as x -> if x > 0 then ValidInt x else Invalid
| :? string as x -> if x.Length > 0 then ValidString x else Invalid
| _ -> Invalid
В этот момент вызывающие абоненты могут совпадать и быть уверенными, что логика была применена.
match someValue with
| ValidInt x -> // ...
| _ -> // ...