Lift Record / Scala Typed Traits correct Pattern Matching

180 views
Skip to first unread message

Alexander

unread,
Nov 24, 2011, 5:22:16 AM11/24/11
to Lift
I am currently working on a E-Commerce application in scala / lift and
cannot figure out how to match correctly on my type hierarchy. my
current implementation is:

abstract trait BaseProduct[T <: BaseProduct[T]] extends
MongoRecord[T] with ObjectIdPk[T] {
self:T =>
def whatever
...
}

abstract trait SimpleType[T <: BaseProduct[T]] extends
BaseProduct[T] {
self:T =>
val producttype = "product/simple"
}

abstract trait ConfigurableType[T <: BaseProduct[T],E <:
SimpleType[E]] extends BaseProduct[T] {
self: T =>
val producttype = "product/configurable"
}

class ClothingProduct extends SimpleType[ClothingProduct] {
def meta = ClothingProduct
}

class ConfigurableClothing extends
ConfigurableType[ConfigurableClothing,ClothingProduct] {
val childmeta = ClothingProduct
val configurableFields = List(color,size)
def meta = ConfigurableClothing
}

With this in place I want to implement a Shopping Cart which should
only take Products of Type SimpleType (and BaseProduct). It should
also implement a function that takes any kind of BaseProduct with a
pattern matching clause that should react to wheater it is a Simple or
a Configurable Type.

My first implementations which drives me crazy due to Type Errors was:

object Cart extends SessionVar[List[CartItem]](List()) {
def addProduct(product:SimpleType[_],quantity:Int = 1) = {
this.get.partition(_.product.id.is == product.id.is) match {
case (Nil,xs) => this.set(CartItem(product,quantity) :: xs)
case (x,xs) => this.set(CartItem(product,x.head.quantity +
quantity) :: xs)
}
}
}

case class CartItem(product:SimpleType[_], quantity:Int) {
def lineTotal:Double = quantity * product.price.is
}

With to following function to add a Cart Item:

def addBasketLink(prod:BaseProduct[_]) = {
prod match {
case x:SimpleType[_] => Cart.addProduct(x)
case _ => S.notice("Sorry not possible to add to Basket")
}

My main issue is that "Underscore" definition of the supplied type to
SimpleType which causes type violation errors. I am currently not able
to figure out how to do the wanted typing right. It would be great it
someone could tell me where my error is and properbly explain to me
how I work with typed traits correctly.

Thanks

Tim Nelson

unread,
Nov 27, 2011, 8:12:22 AM11/27/11
to lif...@googlegroups.com
Hi Alexander,

Using inheritance with Record can be a little tricky. I would suggest you try something more like the following:

trait SimpleType {
  def id: ObjectIdField[_]
  def price: IntField[_]
}

trait BaseProduct[T <: BaseProduct[T]] extends MongoRecord[T] with ObjectIdPk[T] {
  self: T =>

  object price extends IntField(this)
}

class ClothingProduct extends BaseProduct[ClothingProduct] with SimpleType {
  def meta = ClothingProduct
}
object ClothingProduct extends ClothingProduct with MongoMetaRecord[ClothingProduct]

object Cart extends SessionVar[List[CartItem]](List()) {
 def addProduct(product: SimpleType, quantity: Int = 1) = {
   this.get.partition(_.product.id.is == product.id.is) match {
     case (Nil,xs) => this.set(CartItem(product,quantity) :: xs)
     case (x,xs) => this.set(CartItem(product,x.head.quantity + quantity) :: xs)
   }
 }
}

case class CartItem(product: SimpleType, quantity: Int)  {
 def lineTotal: Double = quantity * product.price.is
}

Tim
Reply all
Reply to author
Forward
0 new messages