简体   繁体   English

Haskell算术运算和任意/固定精度数的DB持久性

[英]Haskell arithmetic operations and DB persistence of arbitrary/fixed precision numbers

As a Haskell (GHC platform) beginner I bumped into a problem of dealing with data types and arithmetic operations related to business domain that involves currency/money operations and I'm looking for a solution. 作为Haskell(GHC平台)的初学者,我遇到了处理与业务领域相关的数据类型和算术运算的问题,涉及货币/货币操作,我正在寻找解决方案。

I'm developing application that is supposed to interface with (independent) accounting module (via web services) while at the same time having a (web) user interface for ad-hoc data entry which is stored in a separate database (PostgreSQL). 我正在开发应该与(独立)会计模块(通过Web服务)接口的应用程序,同时具有用于临时数据输入的(web)用户界面,该用户界面存储在单独的数据库(PostgreSQL)中。

I'm coming from C#/F# environment and System.Decimal covers all the core needs there. 我来自C#/ F#环境,System.Decimal涵盖了那里的所有核心需求。 Please correct me if I'm wrong but Haskell does not seem to have an integrated (default) data type that could be considered equivalent. 如果我错了,请纠正我,但Haskell似乎没有可被视为等效的集成(默认)数据类型。

Ideal choice would be a data type that offers arbitrary precision arithmetic or at least something in the lines of Decimal128 (IEEE 754). 理想的选择是提供任意精度算术的数据类型,或者至少是Decimal128(IEEE 754)中的某些内容。 The type should support rounding (to nearest, ties away from zero and if possible also ties to even) and the following operations: add, subtract, multiply, divide (ideally also square/root). 该类型应该支持舍入(最接近,从零开始,如果可能还与偶数相关)和以下操作:加,减,乘,除(理想情况下也是平方/根)。 Conversions between types should also be supported. 还应支持类型之间的转换。

From what I've managed to find there are two Haskell modules on Hackage that are supposed to perform calculations exactly - Data.Fixed and Data.Decimal (by the way is there any way of creating custom literals in Haskell - eg to copy 123.45m from F# ?). 从我设法发现,Hackage上有两个Haskell模块应该完全执行计算--Data.Fixed和Data.Decimal(顺便说一句,有什么方法可以在Haskell中创建自定义文字 - 例如复制123.45m来自F#?)。 At least the latter would as far as I can tell (after a quick test) enables most of what I've described in previous paragraph, but when I add a DB (PostgreSQL via Persistent/HDBC) and a web framework (YESOD) to the mix things don't look so peachy. 至少后者会尽我所知(在快速测试之后)启用我在前一段中描述的大部分内容,但是当我添加一个数据库(PostgreSQL通过Persistent / HDBC)和一个Web框架(YESOD)时混合的东西看起来不那么好看。 The support there seems to be lacking. 似乎缺乏支持。

Is there any other combination that enables what I've described end-to-end (data entry => data processing => storage) with minimal friction (eg manual casting from string after loading from DB seems odd having a really strongly typed language) and without the loss of precision (any pointers welcome)? 是否有任何其他组合能够以最小的摩擦力实现我所描述的端到端(数据输入=>数据处理=>存储)(例如,从DB加载后从字符串手动转换似乎很奇怪,具有非常强类型的语言)没有精度的损失(任何指针欢迎)?

I am making a Yesod application, and using Database.Persist. 我正在制作Yesod应用程序,并使用Database.Persist。 For my purposes, I'm going to make a newtype wrapping over a Data.Fixed value, and use an Int64 field, like so: 为了我的目的,我将在Data.Fixed值上创建一个newtype,并使用Int64字段,如下所示:

newtype Dollars = Dollars { unDollars :: Centi } deriving (Eq, Num)

instance PersistField Dollars where
   toPersistValue = PersistInt64 . fromIntegral . fromEnum . unDollars
   fromPersistValue (PersistInt64 c) = Right . Dollars . toEnum . fromIntegral $ c
   fromPersistValue x = Left . Text.pack $ "Expected Int64 counting cents, got: " ++ show x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM