当前位置: 首页 > 知识库问答 >
问题:

CATS:为没有类型别名的谓词实现逆变量?

梁巴英
2023-03-14
type Predicate[A] = A => Boolean

implicit val predicateContra = new Contravariant[Predicate] {
  override def contramap[A, B](fa: Predicate[A])(f: B => A): Predicate[B] =
    (b: B) => fa(f(b))
}
val even: Predicate[Int] = (i: Int) => i % 2 == 0

我觉得很烦人。因此,我想知道是否可以直接为Function1从类型变量a到Boolean定义predicateContra,而不是使用类型别名,但我无法使其工作。以下两种想法都给了我一个编译器错误:

implicit val predicateContra = new Contravariant[Function1[_, Boolean]] {
// "Function1[_, Boolean] takes no type parameters, expected: one"

implicit def predicateContra[A] = new Contravariant[Function1[A, Boolean]] {
// "A => Boolean takes no type parameters, expected: one"

我如何告诉编译器我的Function1的第一个参数应该保持一个“hole”,而第二个应该固定为boolean?有可能吗?在查看cats的源代码时,我发现星号在很多地方作为类型参数,但这对我也不起作用。

共有1个答案

闾丘树
2023-03-14

您可以使用kind投影仪,它允许您引用带有星号(*)的“类型孔”。

这使得定义类型*->*的语法非常简单,即一元类型构造函数(使用单个类型生成类型)。例如,使用某种类型a生成类型Map[a,Int]的类型可以简单地写成Map[*,Int]

则您的代码变为:

val strToBool: String => Boolean = _.contains("1")
val intToStr: Int => String = _.toString

def predicateContra = 
  new Contravariant[Function1[*, Boolean]] {
    override def contramap[A, B](fa: A => Boolean)(f: B => A): B => Boolean = 
      (b: B) => fa(f(b))
  }

predicateContra.contramap(strToBool)(intToStr)(42) // false 
predicateContra.contramap(strToBool)(intToStr)(41) // true
def predicateContra =
  new Contravariant[({ type lambda[A] = Function1[A, Boolean] })#lambda] {
      ...
  }
 类似资料:
  • 我是使用谓词的新手,不确定我是否正确理解了它。我有一个抽象的类,其中每小时和薪水员工是分开创建的。我的问题依赖于我的类,我不确定如何检查它是否是每小时员工并返回真或假。 我需要为以下所有条件创建不同的谓词: 所有员工,仅每小时一次,仅限工资和全职。 到目前为止,我只是想先让“仅每小时”谓词正常工作,然后再找出剩下的谓词。我不确定在“p”后面加什么来检查它是哪种类型的员工。我目前拥有的是: 我还有一

  • 编译以下代码时: 我得到一个错误: 错误消息试图说明什么?还有,怎么修? 有一个相关的问题,但解决方案是修改特征<code>a</code>(在我的例子中对应于<code>可绘制</code>),但这在这里是不可能的,因为<code>可以绘制</code>来自外部库。

  • 此代码只是使用中间的来删除重复项,其中元素之间的相等性是根据提供的比较器定义的。 让我们给局部类型推断一个机会吧,我(天真地)想...于是我将上面的代码改为: 这对我来说是有意义的,因为的类型可以从的类型推断出来,或者我是这么想的。但是,修改后的代码无法编译,并生成以下错误: 注意1:编译代码的一种方法是将返回类型更改为。不过,那是一套很难用的... 注意2:另一种方法是在比较器中不使用逆变,但我

  • 下面的lexer语法片段应该根据类中定义的谓词来标记“自定义名称”: CUSTOM_NAME的正确匹配总是尽可能长的匹配。现在,如果lexer遇到一个自定义名称,比如,那么我希望它对整个字符串,然后用'some:cname'作为参数调用一次谓词。 编辑:这种行为的有趣之处在于,只要将部分匹配传递给谓词,谓词的结果似乎完全被lexer忽略了。这似乎效率很低。

  • 我在应用程序中使用Querydsl来大大改进查询数据库的代码。但是,我有一个来自外部服务的JPA谓词(javax.persistence.criteria.Predicate)。我想混合使用Querydsl和外部谓词创建的查询。例如: 另一个解决方案是将Querydsl谓词转换为JPA谓词: 有可能吗?如果是,我如何做到这一点?如果没有,是否有其他混合谓词的解决方案(比如将两者转换为SQL字符串并

  • 我正在尝试在Linux中编译这个repo,但在这一步中遇到了一些麻烦。 *util/BinarySerialization.hpp *序列化/ElementBS.cpp *xdlrc/model/Element.hpp util/BinarySerialization。hpp:在'typename boost::disable_if'的实例化中 ElementB中的第一个writeBinary。c