在 Perl 6 中创建一个 Maybe 类型 [英] Creating a Maybe type in Perl 6

查看:38
本文介绍了在 Perl 6 中创建一个 Maybe 类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多可能会失败的函数,但它们的签名中也定义了返回类型.因为我喜欢尽可能定义变量的类型,所以我想定义一个 Maybe 子集来使用它.我想出了这个:

I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:

subset Maybe is export of Mu where Mu | Failure;

问题在于 FailureMu 的子类,所以这将匹配任何东西,当我真正想要的是能够匹配一个特定的与 Failure 一起动态输入.我的下一个想法是创建一个参数化角色以用作类型,因为我不想为每个可能也是 Failure 的类型创建子集.我想它看起来像这样:

The problem with this is Failure is a subclass of Mu, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure. I imagine it looking something like this:

role Maybe[::T] {
    # ...
}

sub foo(--> Int) { rand < 0.5 ?? 1 !! fail 'oops' }

my Maybe[Int] $foo = foo;

只有我不知道我需要为角色添加什么才能完成这项工作.是否可以创建这样的角色?如果没有,是否有另一种方法可以创建一个类型来做我想做的事?

Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?

推荐答案

Perl6 类型已经是 Maybe 类型了.

Perl6 types are already Maybe types.

只是 Perl6 与大多数其他具有 Maybe 类型的语言不同,它具有类型化的空值.

It's just that Perl6 has typed nulls unlike most other languages with Maybe types.

这是Maybe[Int]变量:

my Int $a;
my Int:_ $a; # more explicit

这里有一个明确的Int:

my Int:D $a = …; # must be assigned because the default is not "definite"

这包含一个空 Int:

my Int:U $a;

<小时>

请注意,FailureNil 的子类型,因此即使是指定了返回类型的子例程也可以返回它们.
(Nil 与其他语言中的 nullnil 不同.)


Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)

sub foo ( --> Int:D ) { Bool.pick ?? 1 !! fail 'oops' }

my $foo = foo; # $foo contains the failure object

Nil 实际上是一种通用的软故障.当分配给一个变量时,它只是将其重置为默认值.

Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.

my Int $foo = 1;

$foo = Nil;

say $foo.perl; # Int

my Int:D $bar is default(42) = 1;

$bar = Nil

say $bar.perl; # 42

典型的默认值与类型相同.

The typical default is the same as the type.

my Int $foo;

say $foo.VAR.default.perl; # Int

一个特定的软失败是返回一个类型对象

A specific soft failure would be to return a type object

sub foo ( --> Int ){
  Bool.pick ?? 1 !! Int
}

这就是为什么我说 Nil通用"软故障.

That is why I said Nil is a "generic" soft failure.

通常,如果您要定义变量的类型,则希望它属于该类型.因此,如果您的代码得到其他类型的东西,它应该立即抱怨.

Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.

有更好的方法来处理失败.

sub foo(--> Int:D ) { rand < 0.5 ?? 1 !! fail 'oops' }

with foo() -> Int:D $foo {
  … # use $foo here
} else -> $fail {
  … # use $fail here
}

这是可行的,因为 Failure 总是认为自己是未定义的.

This works because Failure always sees itself as being undefined.

您也可以将其与 when

given foo() {
  when Int:D -> Int:D $foo {
    … # use $foo here
  }
  when Failure:D -> Failure:D $fail {
    # a DEFINITE Failure value
    # (`DEFINITE` is different than `defined`.)
  }
  default {
    … # handle unexpected values (can be removed if not needed)
  }
}

或者只是定义或运算符 // 如果你不关心它是什么类型的失败.

Or just the defined-or operator // if you don't care what kind of failure it is.

my Int:D $foo = foo() // 1;

您甚至可能想用它来将 Failure 变成 Nil.

You may even want to use that to turn a Failure into a Nil.

my Int:D $foo is default(42) = foo() // Nil;

<小时>

如果你真的想要一个可能失败的子集,我认为这应该可行:


If you really want a maybe-failure subset, I think this should work:

sub Maybe-Failure ( Any:U ::Type ) {
  anon subset :: of Any where Type | Failure
}

my constant Maybe-Int = Maybe-Failure(Int);

# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;

它目前不起作用.

(注意你不应该处理 Mu 除非你需要专门处理 Any 类型之外的类型和值;比如 JunctionIterationEnd.)

(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)

可能也应该起作用的其他东西是:

Something else that should probably also work is:

my class Maybe-Failure {
  method ^parameterize ( $, Any:U ::Type ) {
    anon subset :: of Any where Type | Failure
  }
}

my Maybe-Failure[Int] $foo;

这似乎与另一个失败的原因相同.

This seems like it fails for the same reason the other one does.

另一种方法是创建一种新类型的类,例如 subset.
那就是 subset 使用与 Perl6 中其他类不同的 MOP.

Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.

这篇关于在 Perl 6 中创建一个 Maybe 类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆