嘿,所以我在阅读关于类型驱动开发的this post。我在摸索Java类型时遇到了困难,所以我尝试用Haskell编写它。不过,我有两个问题:
data Dollar = Dollar Double,像Dollar 4.0这样的值是货币,而Dollar是货币。我认为Dollar :: Double -> Dollar是不出口的东西。exchange :: (Money a, Money b) =>[ExchangeRate] -> a -> b的东西。然后,银行只是一个包含ExchangeRates集合的对象,但我不知道ExchangeRate是什么类型。到目前为止,我的代码是:
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)。
发布于 2014-12-10 19:14:19
不别用打字机。让我们从基础开始:
那么,您想表示不同的货币类型吗?让我们使用一个简单的代数数据类型:
data CurrencyType = Dollar | Franc deriving (Show)要表示货币,请再次使用简单的数据类型:
data Money = Money {
amount :: Double,
mType :: CurrencyType
} deriving (Show)在ghci中的一些演示:
*Main> let fiveDollars = Money 5 Dollar
*Main> fiveDollars
Money {amount = 5.0, mType = Dollar} 现在,您需要将货币从一种货币类型转换为另一种货币类型的能力。这同样可以通过一个简单的函数来实现:
convertMoney :: CurrencyType -> Money -> Money
convertMoney Dollar money = undefined -- logic for Converting money to Dollar
convertMoney Franc money = undefined -- logic for converting money to Franc 我对类型化的一般规则是,当我想要表示某些特定的抽象时,它有一些定义明确的规律。对于大多数情况下,简单的数据类型和对它们进行操作的函数将成为一个很好的案例。
根据您的评论更新:如果您希望能够声明自己的货币类型,那么您可以遵循以下方法:
data CurrencyType a = CurrencyType a deriving (Show)
data Dollar = Dollar deriving (Show)
data Money a = Money Double (CurrencyType a) deriving (Show)在ghci中演示:
λ> let fiveDollars = Money 5 (CurrencyType Dollar)
λ> fiveDollars
Money 5.0 (CurrencyType Dollar)现在,假设您想要定义另一个货币Franc。然后为它定义一个数据类型:
data Franc = Franc deriving (Show)然后你可以用它来定义金钱:
λ> 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.
嗯,你可以。
convertFromDollar :: Money Dollar -> Money Franc
convertFromDollar x = undefined -- Write your logic here 发布于 2014-12-10 22:35:55
根据我如何在PHP工作中实现它,我将如何在Haskell中实现它:
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 usdPricehttps://stackoverflow.com/questions/27408873
复制相似问题