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

时间:2012-08-30 17:10:55

标签: haskell persistent yesod hdbc

作为一名Haskell(GHC平台)的初学者,我遇到了一个问题,即处理涉及货币/货币操作的业务领域的数据类型和算术运算,我正在寻找解决方案。

我正在开发应该与(独立)会计模块(通过Web服务)接口的应用程序,同时具有用于临时数据输入的(Web)用户界面,该应用程序存储在单独的数据库中( PostgreSQL的)。

我来自C#/ F#环境,System.Decimal涵盖了那里的所有核心需求。如果我错了,请纠正我,但Haskell似乎没有可被视为等效的集成(默认)数据类型。

理想的选择是提供任意精度算术的数据类型,或者至少是Decimal128(IEEE 754)中的某些内容。该类型应该支持舍入(最接近,从零开始,如果可能还与偶数相关)和以下操作:加,减,乘,除(理想情况下也是平方/根)。还应支持类型之间的转换。

从我设法发现,Hackage上有两个Haskell模块应该完全执行计算 - Data.Fixed和Data.Decimal(顺便说一下,在Haskell中有任何创建自定义文字的方法 - 例如从F#复制123.45米?)。至少后者会尽我所知(在快速测试之后)启用我在前一段中描述的大部分内容,但是当我添加一个数据库(PostgreSQL通过Persistent / HDBC)和一个Web框架(YESOD)时混合的东西看起来不那么好看。似乎缺乏支持。

是否有任何其他组合能够以最小的摩擦力实现我所描述的端到端(数据输入=>数据处理=>存储)(例如,从DB加载后从字符串手动转换似乎很奇怪非常强类型的语言)并且没有精度损失(任何指针欢迎)?

1 个答案:

答案 0 :(得分:2)

我正在制作Yesod应用程序,并使用Database.Persist。为了我的目的,我将在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