首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在货币之间建立货币、货币和银行的模型?

如何在货币之间建立货币、货币和银行的模型?
EN

Stack Overflow用户
提问于 2014-12-10 19:04:23
回答 2查看 2.9K关注 0票数 13

嘿,所以我在阅读关于类型驱动开发的this post。我在摸索Java类型时遇到了困难,所以我尝试用Haskell编写它。不过,我有两个问题:

  1. 我不知道如何实现货币和实际货币之间的区别。起初,我认为货币只是货币的类型(我认为这是合理的),就像这个data Dollar = Dollar Double,像Dollar 4.0这样的值是货币,而Dollar是货币。我认为Dollar :: Double -> Dollar是不出口的东西。
  2. 这就导致了一个问题,那就是我无法为一家可以兑换货币的银行建模。我在想一些类似exchange :: (Money a, Money b) =>[ExchangeRate] -> a -> b的东西。然后,银行只是一个包含ExchangeRates集合的对象,但我不知道ExchangeRate是什么类型。

到目前为止,我的代码是:

代码语言:javascript
复制
class Money m where
    money :: (Money m) => Double -> m
    amount :: (Money m) => m -> Double
    add :: (Money m) => m -> m -> m
    add a b = money $ amount a + amount b

class (Money a, Money b) => ExchangeablePair a b where

newtype Dollar = Dollar Double
                 deriving (Show, Eq)

instance Money Dollar where
    money = Dollar
    amount (Dollar a) = a

newtype Franc = Franc Double
                 deriving (Show, Eq)

instance Money Franc where
    money = Franc
    amount (Franc a) = a

instance ExchangeablePair Dollar Franc where

编辑:我仍然想要这样的东西的安全:buyAmericanBigMac :: Dollar -> (BigMac, Dollar)

EN

回答 2

Stack Overflow用户

发布于 2014-12-10 19:14:19

不别用打字机。让我们从基础开始:

那么,您想表示不同的货币类型吗?让我们使用一个简单的代数数据类型:

代码语言:javascript
复制
data CurrencyType = Dollar | Franc deriving (Show)

要表示货币,请再次使用简单的数据类型:

代码语言:javascript
复制
data Money = Money {
      amount :: Double,
      mType :: CurrencyType
    } deriving (Show)

在ghci中的一些演示:

代码语言:javascript
复制
*Main> let fiveDollars = Money 5 Dollar
*Main> fiveDollars
Money {amount = 5.0, mType = Dollar}   

现在,您需要将货币从一种货币类型转换为另一种货币类型的能力。这同样可以通过一个简单的函数来实现:

代码语言:javascript
复制
convertMoney :: CurrencyType -> Money -> Money
convertMoney Dollar money = undefined -- logic for Converting money to Dollar                
convertMoney Franc money = undefined -- logic for converting money to Franc  

我对类型化的一般规则是,当我想要表示某些特定的抽象时,它有一些定义明确的规律。对于大多数情况下,简单的数据类型和对它们进行操作的函数将成为一个很好的案例。

根据您的评论更新:如果您希望能够声明自己的货币类型,那么您可以遵循以下方法:

代码语言:javascript
复制
data CurrencyType a = CurrencyType a deriving (Show)

data Dollar = Dollar deriving (Show)

data Money a = Money Double (CurrencyType a) deriving (Show)

在ghci中演示:

代码语言:javascript
复制
λ> let fiveDollars = Money 5 (CurrencyType Dollar)
λ> fiveDollars
Money 5.0 (CurrencyType Dollar)

现在,假设您想要定义另一个货币Franc。然后为它定义一个数据类型:

代码语言:javascript
复制
data Franc = Franc deriving (Show)

然后你可以用它来定义金钱:

代码语言:javascript
复制
λ> let fiveFranc = Money 5 (CurrencyType Franc)
λ> fiveFranc
Money 5.0 (CurrencyType Franc)

>> I can't write a function that only takes Dollars at compile time.

嗯,你可以。

代码语言:javascript
复制
convertFromDollar :: Money Dollar -> Money Franc
convertFromDollar x = undefined -- Write your logic here     
票数 7
EN

Stack Overflow用户

发布于 2014-12-10 22:35:55

根据我如何在PHP工作中实现它,我将如何在Haskell中实现它:

代码语言:javascript
复制
module Money where


-- For instance Show Money
import Text.Printf


-- Should perhaps be some Decimal type
type Amount = Double


-- Currency type
data Currency = Currency { iso4217 :: String } deriving Eq

instance Show Currency where
    show c = iso4217 c


-- Money type
data Money = Money { amount :: Amount, currency :: Currency }

instance Show Money where
    show m = printf "%0.2f" (amount m) ++ " " ++ show (currency m)


-- Conversion between currencies
data BasedRates = BasedRates { base :: Currency, rate :: Currency -> Amount }

type CrossRates = Currency -> Currency -> Amount

makeCrossRatesFromBasedRates :: BasedRates -> CrossRates
makeCrossRatesFromBasedRates (BasedRates { base=base, rate=rate }) = 
    \ fromCurrency toCurrency -> rate toCurrency / rate fromCurrency


convert :: CrossRates -> Currency -> Money -> Money
convert crossRates toCurrency (Money { amount=amount, currency=fromCurrency }) 
    = Money { amount = crossRates fromCurrency toCurrency * amount, currency=toCurrency }



-- Examples

sek = Currency { iso4217 = "SEK" }
usd = Currency { iso4217 = "USD" }
eur = Currency { iso4217 = "EUR" }

sekBasedRates = BasedRates {
    base = sek,
    rate = \currency -> case currency of
        Currency { iso4217 = "SEK" } -> 1.0000
        Currency { iso4217 = "USD" } -> 6.5432
        Currency { iso4217 = "EUR" } -> 9.8765
}

crossRates = makeCrossRatesFromBasedRates sekBasedRates

usdPrice = Money { amount = 23.45, currency = usd }
sekPrice = convert crossRates sek usdPrice
eurPrice = convert crossRates eur usdPrice
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27408873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档