【发布时间】:2020-12-08 22:14:48
【问题描述】:
我是否需要一个定制的 sum 类型才能定义一个 A 类型列表的数据类型,其中最后一个元素是 B 类型(因此必须重新实现其上定义的所有不错的函数)。
type ListTerminatedWith<'a,'b> =
| Cons of 'a * ListTerminatedWith<'a,'b>
| Nil of 'b
好的,那么显而易见的是:
type ListTerminatedWith<'a,'b> = List<'a> * 'b
但是,实际上我只想在到达那里时将终止值附加到列表中(真正的问题是关于 Seq,而不是 List)。
一个奇怪的例子是让我们把值的总和说成一个字符串。
所以(在完整的伪代码中......我不希望它编译)
let x: ListTerminatedWith<int,string> = [ 1;2;3;"6"]
这个值是由一个函数创建的,其中“6”被附加,当函数想要终止时,就像创建一个序列一样。
【问题讨论】:
-
也许您可以使用
Either<'a, 'b>类型的列表来解决?但无论哪种方式,您可能都必须编写 sum 等函数,因为默认值不起作用。 -
这允许 'a 和 'b 的任意组合......我不想重新发明的是 map/bind/fold 等......但也许我被它困住了
-
好吧,你有一个非常具体的案例,恐怕你必须这样做,除非这两种类型都展示了可以与 SRTP 一起使用的方法。在这种情况下,您可以使用更简单的标准函数重新定义。在你自己的集合类型上定义映射、绑定、过滤、折叠是很常见的,尤其是如果它们不能是
IEnumerable。 -
它是具体的,但事实上,正如我所展示的,它实际上是 List 的概括,其中 Nil 也有一个值。 (对我而言)很有趣的是,List 的这种微不足道的扩展实际上似乎无法表达,而不涉及原子类型。
-
Fwiw,你没有一个简单的 List 扩展,你有自己的类型。列表定义为
List<'t>,您的类型定义为MyList<'a, 'b>。任何现有代码如何能够处理任意类型参数,在您的情况下,还附加了特定规则?