gpt4 book ai didi

scala - 对两种类型之间的二元关系建模

转载 作者:行者123 更新时间:2023-12-04 08:20:41 25 4
gpt4 key购买 nike

有企业和人。用户可以喜欢或发表关于企业的评论,但同样如此不能发生在一个人身上。当用户发布有关某项业务或喜欢它的内容时,该业务称为 target喜欢或发布:

trait TargetingRelation[TargetingType[_],TargetedType]

class Business

class Person

class Post[Target | TargetingRelation[Business,Post] ] {
def target:Target
}

class Like[Target | TargetingRelation[Business,Like] ] {
def target:Target
}

我在这里发明了一个 T | P[T]符号含义类型参数 T使得它满足某些性质 P[T] (或 T :|: P[T] 如果它具有更多类型吸引力)。在代码中的其他地方,我想要声明如下:
object canPostAboutBusiness extends TargetingRelation[Post,Business] 
object canLikeBusiness extends TargetingRelation[Like,Business]

这些对象实际上是证据,类似于 Haskell 类型类。所以这将键入检查:
val p = new Post[Business]
val l = new Like[Business]

但是 不是 这个:
val p = new Post[Person]
val l = new Like[Person]

就我对 Scala 的了解而言,我无法以令人满意的方式对这种特定的事态进行建模。现在我坚持认为这是 不是 子类型,因为业务是 不是 A:
class Business extends 
TargetingRelation[Post,Business] with
TargetingRelation[Like,Business]

事实上, Business 是非常可取的。仍然完全不知道 Post .这种关系实际上是在两者之外 PostBusiness .此外,我想上面的代码甚至无法编译,因为 Business继承自 TargetingRelation两次。见解是最受欢迎的。

相关: Using a context bound in a class type parameter

最佳答案

您可以在 Scala 中使用隐式函数,使用类似于类型类的东西来执行此操作。例如:

import scala.language.higherKinds

trait TargetingRelation[A[_], B]

class Business
class Person

// Using explicitly declared implicit parameter:
class Post[T](implicit ev: TargetingRelation[Post, T])

// Using a "context bound". The syntax is a little hairy and uses
// a type lambda because TargetingRelation takes multiple type params
class Like[T : ({type S[x] = TargetingRelation[Like, x]})#S]

implicit object canPostAboutBusiness extends TargetingRelation[Post,Business]
implicit object canLikeBusiness extends TargetingRelation[Like,Business]

然后你可以用 Business 实例化这些类
scala> val p = new Post[Business]
p: Post[Business] = Post@374c991a

scala> val l = new Like[Business]
l: Like[Business] = Like@1fd348f8

但不是 Person
scala> val p1 = new Post[Person]
<console>:15: error: could not find implicit value for parameter ev: TargetingRelation[Post,Person]
val p1 = new Post[Person]
^

scala> val p2 = new Like[Person]
<console>:15: error: could not find implicit value for evidence parameter of type TargetingRelation[Post,Person]
val p2 = new Like[Person]
^

如果你从“scala typeclasses”中搜索,你会发现很多 explanations of the details这是如何工作的,但基本上,您需要构造函数采用 TargetingRelation[TargetingType[_],TargetedType] 类型的隐式参数。然后在构造类( PostLike )时在范围内放置该类型的隐式。隐式作为 TargetedType 的“证据”有一个类型类的实例(并扮演在其他语言类型类实现中自动传递的方法的显式字典的角色)。

事实上,scala 有一些合成糖可以帮助解决这个问题,称为 Context Bound .这会导致方法写为:
def a[A: B] = ???

翻译成
def a[A](implicit ev: B[A]) = ???

在您的特定示例中,上下文边界语法有点棘手,因为有多个类型参数,但可以作为 this SO question 完成。描述。

关于scala - 对两种类型之间的二元关系建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20438322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com