Scala:基于同一层次结构的另一类型参数值限制参数
这个问题可能有点令人困惑,但其目的是: 我想将一个值限制为paremeter类型层次结构中的另一个值。考虑到它们都是类型,如果能强制执行类似的代码就好了Scala:基于同一层次结构的另一类型参数值限制参数,scala,types,type-bounds,Scala,Types,Type Bounds,这个问题可能有点令人困惑,但其目的是: 我想将一个值限制为paremeter类型层次结构中的另一个值。考虑到它们都是类型,如果能强制执行类似的代码就好了 sealed trait Direction case object Buy extends Direction case object Sell extends Direction case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int
sealed trait Direction
case object Buy extends Direction
case object Sell extends Direction
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, ??? -> O is D's OppositeDirection](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])
是有效的,但不应允许我为不正确的配对创建对冲。e、 g:
val invalidHedge = Hedge[Buy, Sell](id = 563, itemId = 10, openingTrade= trade1, closingTrade = trade1)
如有任何建议,将不胜感激
更新:
如果在任何时候我希望我能接受不止一个答案,那就是这一次。所有答案均有效且质量良好。我将选择最能解决问题和产生可读性最强错误的一个。选择的答案有相反的值可供使用(这肯定会派上用场),并且不需要隐含。它还生成一条最清晰的错误消息。类型不等式非常优雅,但是其中有一些神奇的元素,特别是它需要两个消歧。从代码中删除它会停止工作,没有明显的原因。隐式对当然是一个很好的解决方案,它与原始问题非常相似,但没有对立面那么有用,也没有对立面那么自由
感谢大家的精彩回答和快速回复
为了完成,以下是所有重新加工的代码:
object NotEquality {
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null //Without this duplicated line, the compiler will ignore the restriction and silently fail. Why?
}
object Trades {
sealed trait Direction
case object Buy extends Direction
case object Sell extends Direction
import NotEquality._
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit ev: D =!= O)
}
object TradesNeq extends App {
import NotEquality._
import Trades._
val trade1 = Trade[Buy.type](1,10,100)
val trade2 = Trade[Sell.type](2,10,-100)
val validHedge = Hedge[Buy.type, Sell.type](id = 563, itemId = 10, openingTrade= trade1, closingTrade = trade2)
println(s"Valid Hedge: ${validHedge}")
// val invalidHedge = Hedge[Buy.type, Buy.type](563,10,trade1,trade1)
// println(s"InvalidHedge ${invalidHedge}")
}
object TradesDOImpl extends App {
sealed trait Direction
case object Buy extends Direction
case object Sell extends Direction
class TradeDirection[D <: Direction, Op <: Direction]
implicit val BuyToSell = new TradeDirection[Buy.type, Sell.type]
implicit val SellToBuy = new TradeDirection[Sell.type, Buy.type]
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit d: TradeDirection[D, O])
val trade1 = Trade[Buy.type](id = 1, itemId = 10, quantity = 100)
val trade2 = Trade[Sell.type](id = 2, itemId = 10, quantity = -100)
val validHedge = Hedge[Buy.type, Sell.type](id = 563, itemId = 10, openingTrade= trade1, closingTrade = trade2)
println(s"Valid Hedge: ${validHedge}")
val invalidHedge = Hedge[Buy.type, Buy.type](563,10,trade1,trade1)
println(s"InvalidHedge ${invalidHedge}")
}
object TradesOpposite extends App {
sealed trait Direction
abstract class OppositeDirection[D <: Direction](val opposite: D) extends Direction
abstract class Buy(opposite: Sell) extends OppositeDirection[Sell](opposite)
case object Buy extends Buy(Sell)
abstract class Sell(opposite: Buy) extends OppositeDirection[Buy](opposite)
case object Sell extends Sell(Buy)
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, O <: OppositeDirection[D]](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])
val trade1 = Trade[Buy](id = 1, itemId = 10, quantity = 100)
val trade2 = Trade[Sell](id = 2, itemId = 10, quantity = -100)
val validHedge = Hedge[Buy, Sell](id = 563, itemId = 10, openingTrade= trade1, closingTrade = trade2)
println(s"Valid Hedge: ${validHedge}")
// val invalidHedge = Hedge[Buy, Buy](563,10,trade1,trade1)
// println(s"InvalidHedge ${invalidHedge}")
}
对象质量{
特质=!=[A,B]
隐式def neq[A,B]:A=!=B=null
隐式定义neqAmbig1[A]:A=!=A=null
隐式def neqAmbig2[A]:A=!=A=null//如果没有此重复行,编译器将忽略该限制并以静默方式失败。为什么?
}
实物交易{
封闭性状方向
case对象扩展方向
case对象扩展方向
进口质量_
案例类交易[D您可以将每个方向
对象的类型参数化为其相反的方向
:
trait OppositeDirection[D <: Direction] extends Direction
trait Buy extends OppositeDirection[Sell]
case object Buy extends Buy
trait Sell extends OppositeDirection[Buy]
case object Sell extends Sell
特质相反方向[D使用Miles Sabin的答案,你可以:
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null
sealed trait Direction
case object Buy extends Direction
case object Sell extends Direction
type Buy = Buy.type
type Sell = Sell.type
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit ev: D =!= O)
val trade1 = Trade[Buy.type](1,10,100)
val trade2 = Trade[Sell.type](2,10,-100)
trait=!=[A,B]
隐式def neq[A,B]:A=!=B=null
隐式定义neqAmbig1[A]:A=!=A=null
隐式定义neqAmbig2[A]:A=!=A=null
封闭性状方向
case对象扩展方向
case对象扩展方向
类型购买=购买类型
类型Sell=Sell.type
案例类交易[D=!=[A,A]
以及类型为[A]=>=!=[A,A]的方法neqAmbig2
匹配预期类型=!=[购买,购买]
val validHedge=对冲[买入,买入](563,10,交易1,交易1)
您可以使用它:
class TradeDirection[D <: Direction, Op <: Direction]
implicit val BuyToSell = new TradeDirection[Buy.type, Sell.type]
implicit val SellToBuy = new TradeDirection[Sell.type, Buy.type]
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit d: TradeDirection[D, O])
class贸易方向[D]
abstract class OppositeDirection[D <: Direction](val opposite: D) extends Direction
abstract class Buy(opposite: Sell) extends OppositeDirection[Sell](opposite)
case object Buy extends Buy(Sell)
abstract class Sell(opposite: Buy) extends OppositeDirection[Buy](opposite)
case object Sell extends Sell(Buy)
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null
sealed trait Direction
case object Buy extends Direction
case object Sell extends Direction
type Buy = Buy.type
type Sell = Sell.type
case class Trade[D <: Direction](id: Long, itemId: Long, quantity: Int)
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit ev: D =!= O)
val trade1 = Trade[Buy.type](1,10,100)
val trade2 = Trade[Sell.type](2,10,-100)
scala> val validHedge = Hedge[Buy, Sell](563,10,trade1,trade2)
validHedge: Hedge[Buy.type,Sell.type] = Hedge(563,10,Trade(1,10,100),Trade(2,10,-100))
scala> val invalidHedge = Hedge[Buy, Buy](563,10,trade1,trade1)
<console>:1: error: ambiguous implicit values:
both method neqAmbig1 of type [A]=> =!=[A,A]
and method neqAmbig2 of type [A]=> =!=[A,A]
match expected type =!=[Buy,Buy]
val validHedge = Hedge[Buy, Buy](563,10,trade1,trade1)
class TradeDirection[D <: Direction, Op <: Direction]
implicit val BuyToSell = new TradeDirection[Buy.type, Sell.type]
implicit val SellToBuy = new TradeDirection[Sell.type, Buy.type]
case class Hedge[D <: Direction, O <: Direction](id: Long, itemId: Long, openingTrade: Trade[D], closingTrade: Trade[O])(implicit d: TradeDirection[D, O])