Skip to content

Instantly share code, notes, and snippets.

@j5ik2o
Last active June 16, 2021 23:54
Show Gist options
  • Save j5ik2o/392c2565aaac809f8d9c9bf870e38e70 to your computer and use it in GitHub Desktop.
Save j5ik2o/392c2565aaac809f8d9c9bf870e38e70 to your computer and use it in GitHub Desktop.
use iso_4217::CurrencyCode;
use rust_decimal::prelude::FromPrimitive;
use rust_decimal::Decimal;
#[derive(Debug, Clone, PartialEq)]
pub struct Money {
pub amount: Decimal,
pub currency: CurrencyCode,
}
#[derive(Debug, PartialEq)]
pub enum MoneyError {
NotSameCurrencyError,
}
impl Money {
pub fn new(amount: Decimal, currency: CurrencyCode) -> Self {
Self { amount, currency }
}
}
trait Adder {
type Output;
fn add(self, rhs: Self) -> Self::Output;
}
impl Adder for Money {
type Output = Result<Money, MoneyError>;
fn add(mut self, rhs: Self) -> Self::Output {
if self.currency != rhs.currency {
Err(MoneyError::NotSameCurrencyError)
} else {
self.amount += rhs.amount;
Ok(self)
}
}
}
fn main() {
let money1: Money = Money::new(Decimal::from_f32(1.0).unwrap(), CurrencyCode::JPY);
let money2: Money = Money::new(Decimal::from_f32(1.0).unwrap(), CurrencyCode::JPY);
let money3: Result<Money, MoneyError> = money1.add(money2);
println!("{:?}", money3);
}
import java.util.Currency
final case class Money(amount: BigDecimal, currency: Currency)
object Money {
implicit object MoneyAdder extends Adder[Money] {
override type Output = Either[Exception, Money]
override def add(self: Money, rhs: Money): Either[Exception, Money] = {
if (self.currency != rhs.currency) {
Left(new IllegalArgumentException(s"Invalid currency: self = $self, rhs = $rhs"))
} else {
Right(Money(self.amount + rhs.amount, self.currency))
}
}
}
}
trait Adder[A] {
type Output
def add(self: A, rhs: A): Output
}
object Adder {
implicit class AdderOps[A](self: A) {
def add(rhs: A)(implicit ev: Adder[A]): ev.Output = {
ev.add(self, rhs)
}
}
}
object Main extends App {
import Adder.AdderOps
val money1: Money = Money(BigDecimal("1.0"), Currency.getInstance("JPY"))
val money2: Money = Money(BigDecimal("1.0"), Currency.getInstance("JPY"))
val money3: Either[Exception, Money] = money1.add(money2)
println(money3.toString)
}
case class Money(amount: BigDecimal, currency: Currency)
enum MoneyError:
case InvalidCurrency(message: String)
given Adder[Money] with
override type Output[A] = Either[MoneyError, A]
extension (self: Money) def add(rhs: Money): Output[Money] =
if (self.currency != rhs.currency) then
Left(MoneyError.InvalidCurrency(s"Invalid currency: self = $self, rhs = $rhs"))
else
Right(Money(self.amount + rhs.amount, self.currency))
import java.util.Currency
trait Adder[A]:
type Output[A]
extension (self: A) def add(rhs: A): Output[A]
@main def main: Unit =
val money: Money = Money(BigDecimal(10), Currency.getInstance("JPY"))
val result: Either[MoneyError, Money] = money.add(money)
println(result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment