假设我有一些带有关联二进制操作的类型,感觉很像append
,除了操作可能失败。例如,这是List[Int]
的包装器,它只允许我们“添加”具有相同长度的列表:
case class Foo(xs: List[Int]) {
def append(other: Foo): Option[Foo] =
if (xs.size != other.xs.size) None else Some(
Foo(xs.zip(other.xs).map { case (a, b) => a + b })
)
}
这是一个玩具示例,但它与我的实际用例有一个共同点,就是我们可以原则上使用类型系统来使操作完全 - 在这种情况下使用Shapeless的Sized
之类跟踪列表的长度,这样添加不等长度的列表将是编译时错误而不是运行时失败。这并不算太糟糕,但在我的实际用例中,管理类型系统中的约束需要更多的工作并且不太实际。
(在我的用例中,我有一个明智的身份,不像这个玩具示例,但我们现在可以忽略它。)
是否有一些原则性的方法来做这种事情?在Hoogle上搜索a -> a -> m a
或a -> a -> Maybe a
并未发现任何有趣的内容。我知道我可以编写一个临时的append
方法,它只返回我用于模拟失败的任何类型的结果,但是有一些更通用的东西可以给我{{1免费 - 尤其是因为这不是我第一次发现自己想要这种东西。