TL; DR См. Собственный ответ @ Kaiepi для решения. Но каждый не родной тип в P6 уже автоматически представляет собой расширенный обнуляемый тип, который похож на расширенный тип Maybe. Так что это тоже нужно обсудить. Чтобы помочь структурировать мой ответ, я притворюсь, что это проблема XY , хотя это не так.
Решение Y
Я хочу определить Maybe subset
, чтобы использовать для этого
См. Ответ @ Kaiepi.
Все не родные типы P6 уже схожи с типами Maybe
Решение subset
излишне для того, что wikipedia определяет как тип Maybe, который сводится к:
None
[или] исходный тип данных
Оказывается, что все неродные типы P6 уже похожи на расширенный тип Maybe.
Улучшение в том, что (P6 эквивалент a) None
знает, с каким исходным типом данных он был связан:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Решение X
У меня есть много функций, которые могут не работать, но также есть тип возвращаемого значения, определенный в их сигнатуре.
Как вы, вероятно, знаете, если только не действует use fatal;
, P6 сознательно позволяет подпрограммам возвращать сбои, даже если есть проверка типа возврата, которая явно не разрешает их. (A subset
проверка типа возврата может явно отклонить их.)
Таким образом, учитывая, что проверка типа возврата Foo
автоматически превращается во что-то похожее на subset
с предложением where Failure | Foo
, понятно, что вы решили приспособить это, создав соответствующее подмножество, чтобы вы могли принять результат при присвоении переменной.
Но, как мы надеемся, ясно из предыдущего обсуждения, может быть, лучше использовать встроенный аспект системы типов P6, который похож на типы Maybe.
A Nil
может использоваться для обозначения так называемой доброкачественной ошибки. Таким образом, следующее работает для обозначения сбоя (как вы хотите сделать в некоторых из ваших подпрограмм) и устанавливают получающую переменную равной None
(или, скорее, расширенному эквиваленту P6 единицы):
sub foo (--> Int) { Nil }
my Int $bar = foo;
say $bar; # (Int)
Таким образом, вы можете заменить вызовы на fail
на return Nil
(или просто Nil
).
Можно представить себе прагму (называемую, скажем, failsoft
), которая превращает все Failure
с в доброкачественную неудачу Nil
с:
use failsoft;
sub foo (--> Int) { fail }
my Int $bar = foo;
say $bar; # (Int)
Обнуляемые типы
Введение в Википедии о типах Maybe также гласит:
Отличное, но связанное понятие ... называется обнуляемыми типами (часто выражается как A?
).
Самый близкий к P6 эквивалент синтаксиса Int?
, используемый некоторыми языками для выражения обнуляемого Int
, просто Int
без знака вопроса. Ниже приведены допустимые ограничения типов:
Int
- эквивалент P6 обнуляемого Int
или Maybe Int
Int:D
- эквивалент P6 ненулевого значения Int
или Just Int
Int:U
- P6 эквивалент Int
ноль или (Int) None
(:D
и :U
называются смайликами типа по очевидной причине.:))
Продолжая, Википедия Обнуляемые типы страница говорит:
В статически типизированных языках обнуляемый тип имеет тип [a Maybe] (в терминах функционального программирования), тогда как в динамически типизированных языках (где значения имеют типы, а переменные - нет) ), эквивалентное поведение обеспечивается наличием единственного нулевого значения .
В P6:
Значения имеют типы - но переменные тоже.
Типы P6 похожи на расширенный тип Maybe
(как объяснено выше) или на расширенный обнуляемый тип, где имеется столько значений None
s или "null", сколько типов вместо того, чтобы иметь только одиночное None
или нулевое значение.
(Итак, является ли P6 статически типизированным языком или динамически типизированным языком? Это на самом деле Помимо статического против динамического и вместо этого статического и динамического.)
Продолжение:
Примитивные типы, такие как целые числа и логические значения, обычно не могут быть нулевыми, но соответствующие типы, допускающие значения NULL (NULL, целые и NULL, соответственно) могут также принимать значение NULL
.
В P6 все не собственные типы (например, тип с произвольной точностью Int
) похожи на расширенные типы Maybe / nullable.
Напротив, все нативные типы (например, int
- все строчные буквы) являются ненулевыми типами - то, что Википедия называет примитивными типами. Они не могут быть нулевыми или None
:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Наконец, возвращаясь к странице википедии Maybe
:
Основное различие между [возможно] типами и обнуляемыми типами состоит в том, что [возможно] типы поддерживают вложение (Maybe (Maybe A) ≠ Maybe A)
, тогда как обнуляемые типы не (A?? = A?)
.
Встроенные типы P6 не поддерживают вложение таким образом без использования подмножеств. Таким образом, тип P6, в то время как сродни с расширенным типом Maybe
, на самом деле является просто расширенным типом, допускающим обнуление.