如何在Scala中表达Haskell的这种存在类型?
我正在尝试将基于类型类的解决方案应用于Scala。我现在的代码如下。我在Scala中表达存在类型如何在Scala中表达Haskell的这种存在类型?,scala,haskell,typeclass,existential-type,Scala,Haskell,Typeclass,Existential Type,我正在尝试将基于类型类的解决方案应用于Scala。我现在的代码如下。我在Scala中表达存在类型Exp时遇到问题 我怎样才能实现同样的目标 对象表达问题{ //a级评估在哪里 //eval::a->Int 特征评估[A]{ def eval(出口:A):整数 } //数据Exp=forall t.Eval t=>Expr t 密封抽象类 案例类Expr[T](值e:T)(隐式ev:Eval[T])扩展了Exp //实例Eval Exp where //eval(Expr e)=eval e 隐式
Exp
时遇到问题
我怎样才能实现同样的目标
对象表达问题{
//a级评估在哪里
//eval::a->Int
特征评估[A]{
def eval(出口:A):整数
}
//数据Exp=forall t.Eval t=>Expr t
密封抽象类
案例类Expr[T](值e:T)(隐式ev:Eval[T])扩展了Exp
//实例Eval Exp where
//eval(Expr e)=eval e
隐式val exprInstance=新值[Exp]{
def eval(expr:Exp)=expr match{case expr(e,ev)=>ev.eval(e)}
}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//问题就在这里
//数据BaseExp=Const Int | Add Exp Exp | Mul Exp Exp
密封抽象类BaseExpr
case类Const(c:Int)扩展了BaseExpr
case类Add(lhs:Exp,rhs:Exp)扩展了BaseExpr
case类Mul(lhs:Exp,rhs:Exp)扩展了BaseExpr
//实例Eval BaseExp,其中
//评估(常数n)=n
//评估(加上评估)=评估a+评估b
//评估(多个a b)=评估a*b
隐式val BASEXPRINSTANCE=new Eval[BaseExpr]{
def eval(baseExpr:baseExpr)(隐式e:eval[Exp]):Int=
baseExpr匹配{
案例常数(c)=>c
案例添加(左侧、右侧)=>e.eval(左侧)+e.eval(右侧)
案例Mul(左侧、右侧)=>e.eval(左侧)+e.eval(右侧)
}
}
//TODO:有没有一种更简单的方法可以使所有这些都隐式地可转换?
//
//以下内容似乎不起作用:
//
//隐式def baseExprToExp[T Int
特征评估[A]{
def eval(出口:A):整数
}
//////////////////////////////////////////
//这就是魔法
//
//数据Expr=forall t.Eval t=>Expr t
性状表达{
T型
val t:t
Eval evalInst:Eval[T]
}
对象表达式{
def应用[T0:Eval](T0:T0)=新表达式{
类型T=T0
val t=t0
val evalInst=隐式[Eval[T]]
}
}
//需要默认装箱
隐式定义框[T:Eval](T:T)=表达式(T)
//实例Eval Expr where
//eval(Expr e)=eval e
隐式对象表达式扩展了Eval[Expr]{
def eval(expr:expr)=expr.evalInst.eval(expr.t)
}
//data BASEXPR=Const Int | Add Expr Expr | Mul Expr Exp
密封抽象类BaseExpr
case类Const(c:Int)扩展了BaseExpr
案例类添加(lhs:Expr,rhs:Expr)扩展了BaseExpr
case类Mul(lhs:Expr,rhs:Expr)扩展了BaseExpr
//实例Eval BaseExpr,其中
//评估(常数n)=n
//评估(加上评估)=评估a+评估b
//评估(多个a b)=评估a*b
隐式对象baseExprInstance扩展了Eval[BaseExpr]{
def eval(baseExpr:baseExpr):整数=
baseExpr匹配{
案例常数(c)=>c
案例添加(左、右)=>exprInstance.eval(左)+exprInstance.eval(右)
案例Mul(左、右)=>exprInstance.eval(左)+exprInstance.eval(右)
}
}
//所有基表达式的隐式转换
隐式def baseExprToExpr[T您的问题是您正在使用一个提取器(unapply
),但忽略了隐式默认情况下不会作为unapply
的一部分公开这一事实
所以这一行:
def eval(expr: Exp) = expr match { case Expr(e, ev) => ev.eval(e) }
没有case-Expr(e,ev)
,只有case-Expr(e)
,因为只有e
是公开的。要么编写自定义提取器,要么找到不同的方法
Scala确实提供了形式的存在类型:
Expr[T] forSome { type T})
它有一个可用的速记类型符号:Expr[\uz]
不过,您的代码还有一些问题:
如果您在eval
上定义implicit
,则所有实现者都必须使用该特定签名实现eval
函数,您不能像在中那样使用签名中不包含隐式的实现来覆盖eval
implicit val baseExprInstance = new Eval[BaseExpr] {
def eval(baseExpr: BaseExpr)(implicit e: Eval[Exp]): Int =
baseExpr match {
case Const(c) => c
case Add(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
case Mul(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
}
}
接下来,您需要在Expr
上进行T
逆变,或者进行SubExpr
扩展Exp
,您在这里遇到了一个问题:
// instance Eval SubExp where
// eval (Sub a b) = eval a - eval b
implicit val subExprInstance = new Eval[SubExpr] {
def eval(subExpr: SubExpr)(implicit e: Eval[SubExpr]): Int =
e.eval(subExpr.lhs) - e.eval(subExpr.rhs)
}
如果要尝试匹配类型签名,implicit e:Eval[SubExpr]
可以计算T>:SubExpr
的类型,但您需要的是Eval
的Exp
隐式值较低(unapply
),但忽略了这样一个事实,即默认情况下隐式不会作为的一部分公开
所以这一行:
def eval(expr: Exp) = expr match { case Expr(e, ev) => ev.eval(e) }
没有case-Expr(e,ev)
,只有case-Expr(e)
,因为只有e
是公开的。要么编写自定义提取器,要么找到不同的方法
Scala确实提供了形式的存在类型:
Expr[T] forSome { type T})
它有一个可用的速记类型符号:Expr[\uz]
不过,您的代码还有一些问题:
如果您在eval
上定义implicit
,则所有实现者都必须使用该特定签名实现eval
函数,您不能像在中那样使用签名中不包含隐式的实现来覆盖eval
implicit val baseExprInstance = new Eval[BaseExpr] {
def eval(baseExpr: BaseExpr)(implicit e: Eval[Exp]): Int =
baseExpr match {
case Const(c) => c
case Add(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
case Mul(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
}
}
接下来,您需要在Expr
上进行T
逆变,或者进行SubExpr
扩展Exp
,您在这里遇到了一个问题:
// instance Eval SubExp where
// eval (Sub a b) = eval a - eval b
implicit val subExprInstance = new Eval[SubExpr] {
def eval(subExpr: SubExpr)(implicit e: Eval[SubExpr]): Int =
e.eval(subExpr.lhs) - e.eval(subExpr.rhs)
}
如果要尝试匹配类型签名,implicit e:Eval[SubExpr]
可以计算T>:SubExpr
的类型,但您需要的是Exp
implicit foreval更低的Exp
,谢谢!我更新了我的最新帖子,请看一看。在新方法中,我唯一不喜欢的是,我必须删除您指出的隐式参数,但我必须明确指定每一次都要解释。我有什么办法可以避免吗?谢谢!@CălinCruceru我恐怕没有更多的时间了,