trait CanQuantify
[Q
<: Quantity
[T
], T
] { }
def +
(that
: Quantity
[T
])(implicit q
: CanQuantify
[Self, T
], num
: Numeric
[T
]) = { q(value + that.value)
}
def *[R
<: Quantity
[T
]](that
: R
)(implicit num
: Numeric
[T
]) = { Times[T, Self, R](value * that.value)
}
def /
[R
<: Quantity
[T
]](that
: R
)(implicit num
: Fractional
[T
]) = { Per[T, Self, R](value / that.value)
}
}
case class Times
[T, Q
<: Quantity
[T
], R
<: Quantity
[T
]](value
: T
) extends Quantity
[T
] {
def /
(that
: R
)(implicit q
: CanQuantify
[Q, T
], num
: Fractional
[T
]) = { q(value / that.value)
}
}
case class Per
[T, Q
<: Quantity
[T
], R
<: Quantity
[T
]](value
: T
) extends Quantity
[T
] {
def *(that
: R
)(implicit q
: CanQuantify
[Q, T
], num
: Numeric
[T
]) = { q(value * that.value)
}
}
}
}
implicit val productCountCanQuantify
= new CanQuantify
[ProductCount, Double
] { override def apply
(value
: Double
) = ProductCount
(value
) }
implicit val boxCountCanQuantify
= new CanQuantify
[BoxCount, Double
] { }
}
val products
= ProductCount
(10.0) val boxes
= BoxCount
(5.0) n = n * boxes / boxes
}
dHJhaXQgQ2FuUXVhbnRpZnlbUSA8OiBRdWFudGl0eVtUXSwgVF0gewogIGRlZiBhcHBseSh2YWx1ZTogVCk6IFEKfQoKdHJhaXQgUXVhbnRpdHlbVF0gewogIHR5cGUgU2VsZiA8OiBRdWFudGl0eVtUXQoKICBkZWYgdmFsdWU6IFQKCiAgZGVmICsodGhhdDogUXVhbnRpdHlbVF0pKGltcGxpY2l0IHE6IENhblF1YW50aWZ5W1NlbGYsIFRdLCBudW06IE51bWVyaWNbVF0pID0gewogIAlpbXBvcnQgbnVtLl8KICAJcSh2YWx1ZSArIHRoYXQudmFsdWUpCiAgfQoKICBkZWYgKltSIDw6IFF1YW50aXR5W1RdXSh0aGF0OiBSKShpbXBsaWNpdCBudW06IE51bWVyaWNbVF0pID0gewogIAlpbXBvcnQgbnVtLl8KICAJVGltZXNbVCwgU2VsZiwgUl0odmFsdWUgKiB0aGF0LnZhbHVlKQogIH0KCiAgZGVmIC9bUiA8OiBRdWFudGl0eVtUXV0odGhhdDogUikoaW1wbGljaXQgbnVtOiBGcmFjdGlvbmFsW1RdKSA9IHsKICAJaW1wb3J0IG51bS5fCiAgICBQZXJbVCwgU2VsZiwgUl0odmFsdWUgLyB0aGF0LnZhbHVlKQogIH0KfQoKY2FzZSBjbGFzcyBUaW1lc1tULCBRIDw6IFF1YW50aXR5W1RdLCBSIDw6IFF1YW50aXR5W1RdXSh2YWx1ZTogVCkgZXh0ZW5kcyBRdWFudGl0eVtUXSB7CiAgb3ZlcnJpZGUgdHlwZSBTZWxmID0gUGVyW1QsIFEsIFJdCgogIGRlZiAvKHRoYXQ6IFIpKGltcGxpY2l0IHE6IENhblF1YW50aWZ5W1EsIFRdLCBudW06IEZyYWN0aW9uYWxbVF0pID0gewogIAlpbXBvcnQgbnVtLl8KICAJcSh2YWx1ZSAvIHRoYXQudmFsdWUpCiAgfQp9CgpjYXNlIGNsYXNzIFBlcltULCBRIDw6IFF1YW50aXR5W1RdLCBSIDw6IFF1YW50aXR5W1RdXSh2YWx1ZTogVCkgZXh0ZW5kcyBRdWFudGl0eVtUXSB7CiAgb3ZlcnJpZGUgdHlwZSBTZWxmID0gUGVyW1QsIFEsIFJdCgogIGRlZiAqKHRoYXQ6IFIpKGltcGxpY2l0IHE6IENhblF1YW50aWZ5W1EsIFRdLCBudW06IE51bWVyaWNbVF0pID0gewogIAlpbXBvcnQgbnVtLl8KICAJcSh2YWx1ZSAqIHRoYXQudmFsdWUpCiAgfQp9CgpjYXNlIGNsYXNzIFByb2R1Y3RDb3VudCh2YWx1ZTogRG91YmxlKSBleHRlbmRzIFF1YW50aXR5W0RvdWJsZV0gewogIG92ZXJyaWRlIHR5cGUgU2VsZiA9IFByb2R1Y3RDb3VudAp9CgpjYXNlIGNsYXNzIEJveENvdW50KHZhbHVlOiBEb3VibGUpIGV4dGVuZHMgUXVhbnRpdHlbRG91YmxlXSB7CiAgb3ZlcnJpZGUgdHlwZSBTZWxmID0gQm94Q291bnQKfQoKb2JqZWN0IGNhblF1YW50aWZpZXMgewogIGltcGxpY2l0IHZhbCBwcm9kdWN0Q291bnRDYW5RdWFudGlmeSA9IG5ldyBDYW5RdWFudGlmeVtQcm9kdWN0Q291bnQsIERvdWJsZV0gewogICAgb3ZlcnJpZGUgZGVmIGFwcGx5KHZhbHVlOiBEb3VibGUpID0gUHJvZHVjdENvdW50KHZhbHVlKQogIH0KCiAgaW1wbGljaXQgdmFsIGJveENvdW50Q2FuUXVhbnRpZnkgPSBuZXcgQ2FuUXVhbnRpZnlbQm94Q291bnQsIERvdWJsZV0gewogICAgb3ZlcnJpZGUgZGVmIGFwcGx5KHZhbHVlOiBEb3VibGUpID0gQm94Q291bnQodmFsdWUpCiAgfQp9CmltcG9ydCBjYW5RdWFudGlmaWVzLl8KCm9iamVjdCBNYWluIGV4dGVuZHMgQXBwIHsKICB2YWwgcHJvZHVjdHMgPSBQcm9kdWN0Q291bnQoMTAuMCkKICB2YWwgYm94ZXMgPSBCb3hDb3VudCg1LjApCiAgdmFyIG4gPSBwcm9kdWN0cyAvIGJveGVzCiAgbiA9IG4gKiBib3hlcyAvIGJveGVzCn0=