Haskell 试图构建一个应用程序实例来处理不同货币的货币金额,我是否走错了方向?

Haskell 试图构建一个应用程序实例来处理不同货币的货币金额,我是否走错了方向?,haskell,Haskell,我在Haskell(阅读很棒的教程)又试了一次,我正在拼命寻找一个钉子来使用这个巨大的锤子 我的日常工作是电子商务,我们有大量的软件设计问题,操纵价格。所以我想,使用Haskell类型的系统在保证正确性的同时,将货币之间或税前/税后价格之间的转换抽象出来可能会很好 以下是我试图实现的目标的大致概念(显然不是编译,否则就不会出现在这里): 我真正想要的是,如果我只在计算发生时才开始担心转换,而不需要在Money值中嵌入转换函数 那么,我是否走在正确的轨道上,但对某些东西理解错误,或者应用程序真的不

我在Haskell(阅读很棒的教程)又试了一次,我正在拼命寻找一个钉子来使用这个巨大的锤子

我的日常工作是电子商务,我们有大量的软件设计问题,操纵价格。所以我想,使用Haskell类型的系统在保证正确性的同时,将货币之间或税前/税后价格之间的转换抽象出来可能会很好

以下是我试图实现的目标的大致概念(显然不是编译,否则就不会出现在这里):

我真正想要的是,如果我只在计算发生时才开始担心转换,而不需要在
Money
值中嵌入转换函数

那么,我是否走在正确的轨道上,但对某些东西理解错误,或者应用程序真的不是简化此类问题的解决方案

Applicative真的不是简化这类问题的解决方案吗

是的,不是。正如你已经说过的,问题是

(<*>) :: Applicative f => f (a -> b) -> f a -> f b
这也为以后的更改提供了更多的功能。例如,您可以使用幻影类型而不是当前方法来标记货币:

newtype Money c a = Amount a deriving Show

data USD
data EUR

usd :: Num a => a -> Money USD a
usd = Amount

eur :: Num a => a -> Money EUR a
eur = Amount

($+) :: Money c a -> Money c a -> Money c a
(Amount a) $+ (Amount b) = Amount $ a + b

-- eur 5 $+ usd 4 = type error
但是,请记住,对于编译时转换来说,货币是一种非常糟糕的类型,因为汇率一直在变化。更现实的方法是

($+) :: Fractional a => CurrencyEnv -> Money a -> Money a -> Maybe (Money a)

在程序开始时加载
CurrencyEnv
。记住,除非你想向老板解释为什么你少了一些便士,否则你不应该在与货币相关的任务中使用
Double
Data.Ratio.Rational
更合适。

我想你想要的是一个被称为“”,它是一个类型商,用一些代数理论来统一,比如说,dollar.eur^2和eur.dollar.eur

Zeta的解决方案使用“从内部”来确保某些一致性,同时允许人们“从外部”使用您的类型

这是第一步,但等式部分会缺失,这可能是个问题,也可能不是


我认为需要一个环解算器(这不是术语吗?)来处理类型的指数之间的等价性。

Money看起来根本不像一个函子,更不用说是一个应用程序了。谈论
Money String
Money()
Money(Int[Double->IO()])
有意义吗?@n.m.我同意。然而,这可能只是因为
金钱
对于这个想法来说只是一个糟糕的术语。似乎
Money a
只是
a
类型的一个值,上面有一条消息“注意,价格是以C货币表示的”——上面有一个
可能
来处理失败。此外,货币在运行时进行设置和测试(根据实际目标的不同,可能是好的,也可能是坏的…@n.m.谢谢,这样说真的很有说服力:)我不推荐learnyouahaskell用于haskell学习。除非你真的喜欢漫画,但在这方面,还有一些更好的,比如Tintin@nicolas学习哈斯克尔你有什么建议?learnyouahaskell上的漫画不会打扰我,我发现它们让页面更吸引人,也不那么可怕。抛开形式不谈,您是否反对本网站上的内容?对不起,无意中编辑而非评论:使用
×
而不是
*
,或者使用
\*
确保星号不会被解释为标记。
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
($+) :: Money a -> Money a -> Money a
(Amount c a) $+ (Amount c' b) = ...
newtype Money c a = Amount a deriving Show

data USD
data EUR

usd :: Num a => a -> Money USD a
usd = Amount

eur :: Num a => a -> Money EUR a
eur = Amount

($+) :: Money c a -> Money c a -> Money c a
(Amount a) $+ (Amount b) = Amount $ a + b

-- eur 5 $+ usd 4 = type error
($+) :: Fractional a => CurrencyEnv -> Money a -> Money a -> Maybe (Money a)