Scalaz Bind [Seq]类型类

时间:2014-07-15 08:38:25

标签: scala monads typeclass scalaz

我目前正在将一些代码从传统的Scala移植到Scalaz样式。

在我的大多数代码中,在我公开的API签名中使用Seq特征而不是直接使用具体类型(即List,Vector)是相当常见的。但是,这给Scalaz带来了一些问题,因为它没有提供Bind [Seq]类型类的实现。

即。这将正常工作。

List(1,2,3,4) >>= bindOperation

但这不会

Seq(1,2,3,4) >>= bindOperation

失败并显示错误could not find implicit value for parameter F0: scalaz.Bind[Seq]

我认为这是Scalaz中的故意设计决定 - 但我不确定如何在此之前进行预期/最佳实践。

我是否应该将代码直接写入List / Vector而不是使用更灵活的Seq接口?或者我应该简单地定义我自己的Bind [Seq]类型类?

1 个答案:

答案 0 :(得分:11)

集合库执行后空翻以适应子类型:当您对特定集合类型(列表,映射等)使用map时,您(通常)会返回相同的类型。它通过使用an extremely complex inheritance hierarchyCanBuildFrom等类型类来管理这一点。它完成了工作(至少可以说是有争议的),但复杂性并不是很有原则性。一团糟。很多人讨厌它。

作为图书馆用户,复杂性通常很容易避免,但对于图书馆设计师来说,这是一场噩梦。如果我为Seq提供monad实例,则意味着我的所有用户类型都会将层次结构提升到Seq他们使用monadic操作的每种类型。

无论如何,Scalaz人不喜欢非常喜欢子类型,因此大多数情况下Scalaz会停留在层次结构的叶子周围 - ListVector等等。你可以看到对此的一些讨论例如,决定on the mailing list

当我第一次开始使用Scalaz时,我写了很多实用程序代码,试图为Seq等提供实例,并使它们可以与CanBuildFrom一起使用。然后我停了下来,现在我倾向于在我自己的代码中使用ListVectorMapSet跟随Scalaz。如果你致力于“Scalaz风格”,你也应该这样做(或者甚至采用Scalaz自己的IListISet==>>等等。但是,你不会更普遍地就最佳实践找到明确的一致意见,并且这两种方法都可以起作用,所以你只需要尝试找到你喜欢的方法。