Дискриминационные союзы, как правило, используются в качестве держателей данных и дают информацию о том, что они держат, но иногда я сталкиваюсь с необходимостью предотвратить создание дискриминационного союза, но все еще могу сопоставить его с использованием знакомого синтаксиса..
Ради аргумента предположим, что мы представляем URI со строкой, но я хочу создать тип, который имеет гарантированный проверенный URI (т. Е. Он действителен в соответствии с RFC), который также являетсястрока.Просто использование Some / None здесь не работает, так как я все еще хочу получить доступ к любой недопустимой строке.Кроме того, мне нравится мягкий рефакторинг в текущей кодовой базе (заменить существующее объединение в один случай новым объединением в один случай по многим строкам кода гораздо проще, чем в объединении с несколькими случаями).
Я могу решить эту проблему следующим образом, что, я думаю, показывает, что я собираюсь сделать (исключая случаи ошибок для простоты):
[<AutoOpen>]
module VerifiedUriModule =
module VerifiedUri =
type VerifiedUri =
private
| VerifiedUri of string
let create uri = VerifiedUri uri // validation and error cases go here
let tryCreate uri = Some <| VerifiedUri uri // or here
let get (VerifiedUri uri) = uri
let (|VerifiedUri|) x =
VerifiedUri.get x
Дополнительный уровень с AutoOpen
просто разрешить безоговорочный доступ к использованию активного распознавателя.
Я могу в конечном итоге использовать типичный тип Result
, но мне было интересно, является ли это типичной практикой кодирования, или когда я обнаруживаю, что что-то делаювот так, я должен услышать голос в своей голове, говорящий «откат, откат!», потому что я нарушаю классические принципы функционального программирования (не так ли?).
Я понимаю, что это случай сокрытия информации иэто похоже на имитацию поведения класса OO с данными.Каков будет типичный подход F # 'ish (кроме создания класса с закрытым ctor)?