Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中单例类型的GADT类型细化_Scala_Scala Cats_Gadt_Singleton Type - Fatal编程技术网

Scala中单例类型的GADT类型细化

Scala中单例类型的GADT类型细化,scala,scala-cats,gadt,singleton-type,Scala,Scala Cats,Gadt,Singleton Type,我有一个简单的GADT声明如下: T[A] 对象T{ 案例类别MkT[A] 一些(Is.refl[A]) 案例=>无 } //[错误]Main.scala:36:75:类型不匹配; //[错误]发现:猫。证据。是[A,A] //[错误]必填项:猫。证据。Is[A,B] 如何使编译器相信这是正确的 //编辑:正如@Dmytro Mitin指出的那样,执行运行时检查并在编译时说服编译器类型是相同的似乎是自相矛盾的。但这实际上是可能的,并且可以用一个更简单的GADT来演示: SI[A] 对象SI{

我有一个简单的GADT声明如下:

T[A]
对象T{
案例类别MkT[A]
一些(Is.refl[A])
案例=>无
}
//[错误]Main.scala:36:75:类型不匹配;
//[错误]发现:猫。证据。是[A,A]
//[错误]必填项:猫。证据。Is[A,B]
如何使编译器相信这是正确的

//编辑:正如@Dmytro Mitin指出的那样,执行运行时检查并在编译时说服编译器类型是相同的似乎是自相矛盾的。但这实际上是可能的,并且可以用一个更简单的GADT来演示:

SI[A]
对象SI{
大小写对象S扩展SI[字符串]
case对象I扩展SI[Int]
}
def checkInt[A](si:si[A]):选项[Is[A,Int]]=
si匹配{
case SI.I=>Some(Is.refl[Int])
案例=>无
}

通过模式匹配,您可以在运行时(
ta.name==tb.name
)尝试检查“两个
T
对象的单例类型参数是否相同”,但希望在编译时说服编译器。我会尝试使用类型类

trait CheckIs[A, B] {
  def checkIs(ta: T[A], tb: T[B]): Option[Is[A, B]]
}
object CheckIs {
  implicit def same[A]: CheckIs[A, A] = (_, _) => Some(Is.refl[A])
  implicit def diff[A, B]: CheckIs[A, B] = (_, _) => None
}

def checkIs[A, B](ta: T[A], tb: T[B])(implicit ci: CheckIs[A, B]): Option[Is[A, B]] = ci.checkIs(ta, tb)

checkIs(T.MkT("a"), T.MkT("a")) //Some(cats.evidence.Is$$anon$2@28f67ac7)
checkIs(T.MkT("a"), T.MkT("b")) //None

(顺便说一句,
是一个类型类,将其用作隐式约束是很自然的,但将其用作返回类型有点奇怪。)

通过模式匹配,您尝试在运行时检查“两个
T
对象的单例类型参数相同”(
ta.name==tb.name
)但是我想在编译时说服编译器,我会尝试一个类型类

trait CheckIs[A, B] {
  def checkIs(ta: T[A], tb: T[B]): Option[Is[A, B]]
}
object CheckIs {
  implicit def same[A]: CheckIs[A, A] = (_, _) => Some(Is.refl[A])
  implicit def diff[A, B]: CheckIs[A, B] = (_, _) => None
}

def checkIs[A, B](ta: T[A], tb: T[B])(implicit ci: CheckIs[A, B]): Option[Is[A, B]] = ci.checkIs(ta, tb)

checkIs(T.MkT("a"), T.MkT("a")) //Some(cats.evidence.Is$$anon$2@28f67ac7)
checkIs(T.MkT("a"), T.MkT("b")) //None

(顺便说一句,
是一个类型类,将其用作隐式约束是很自然的,但将其用作返回类型有点奇怪。)

这就是GADT的神奇之处:您在运行时进行检查,但它使编译器在编译时确信两种类型是相同的。我添加了一个示例来演示如何使用更简单的GADT,但我想知道它如何使用上面的
T
类型(如果可能的话)。基于类型类的方法没有帮助,因为隐式解析纯粹发生在编译时。@MatthiasBerndt当然Scala对GADT的类型推断支持有限。但是
ta.name==tb.name
太过运行时了。而且您无法连接类型变量
A
b
。基于类型类的方法没有帮助,因为隐式解析纯粹发生在编译时。"为什么这样不好?如果你对编译时解决方案不感兴趣,你应该在你的问题中添加这个限制。这是一件不好的事情,因为如果
t
被一个只有在运行时才知道的字符串参数化,它将不起作用,例如从stdin读取。我没有明确要求,因为它有点明显——这就是GADTs是为了:根据运行时检查得出编译时类型的结论。@MatthiasBerndt好吧,如果
name
可以是运行时字符串,那么,恐怕您通常不可能想要什么。
a@MatthiasBerndt…这里
a
是推断出的
s.type
。但是
隐式地[s.type=:=“abc”]
不编译,
SingleType
s.type
不知道有关
ConstantType
“abc”
。因此,如果在编译时我们不能知道类型
“abc”
“def”
对于两个运行时字符串,那么在编译时,我们无法断定类型是
=:=
,因此我们无法说服编译器。GADT
SI
的示例是不同的。在编译时,我们知道模式
SI.I
具有
A=:=Int
。这就是GADTs的神奇之处:您在运行时进行检查,但它仍然存在在编译时让编译器确信两种类型是相同的。我添加了一个示例来演示如何使用更简单的GADT,但我想知道它如何使用上面的
T
类型(如果可能的话)。基于类型类的方法没有帮助,因为隐式解析纯粹发生在编译时。@MatthiasBerndt当然Scala对GADT的类型推断支持有限。但是
ta.name==tb.name
太过运行时了。而且您无法连接类型变量
A
b
。基于类型类的方法没有帮助,因为隐式解析纯粹发生在编译时。"为什么这样不好?如果你对编译时解决方案不感兴趣,你应该在你的问题中添加这个限制。这是一件不好的事情,因为如果
t
被一个只有在运行时才知道的字符串参数化,它将不起作用,例如从stdin读取。我没有明确要求,因为它有点明显——这就是GADTs是为了:根据运行时检查得出编译时类型的结论。@MatthiasBerndt好吧,如果
name
可以是运行时字符串,那么,恐怕您通常不可能想要什么。
a@MatthiasBerndt…这里
a
是推断出的
s.type
。但是
隐式地[s.type=:=“abc”]
不编译,
SingleType
s.type
不知道有关
ConstantType
“abc”
。因此,如果在编译时我们不能知道类型
“abc”
“def”
对于两个运行时字符串,那么在编译时,我们无法断定类型是
=:=
,因此我们无法说服编译器。GADT
SI
的示例是不同的。在编译时,我们知道模式
SI.I
具有
A=:=Int