haskell - 我可以在 Haskell 中将数字全局限制为只有 3 位小数吗?

我有一个生成 SVG 代码(图像和图标)的包

但是,生成的 svg 代码太大,因为所有数字都有很多小数位。

是否有语言编译指示或类似的东西可以限制所有数字只有 3 位小数?

我想用一些最少的代码来做到这一点,我不想将某些功能单独应用于每个 Float 数字。

最佳答案

不,您不能更改 IEEE 754 浮点运算的工作方式。无论如何,这种变化的影响可能会比您预期的要大得多。幸运的是,您想要的不是改变 float 的表示方式,而是它们的呈现方式。因此,您只需更改实际将 float 写入输出文件的代码,而不是所有涉及 float 的代码。

您在评论中提到您正在使用 blaze-svg 进行渲染。这将有助于包含在问题中,因为它的 API 会影响您可以做什么。那个包我不熟悉,但一眼看去它有一大堆函数和签名

foo :: Show a => a -> Markup

这是一个有点笨拙的签名,因为 Show a => a 只是一种表示字符串的奇怪方式。但这意味着您不能自己格式化字符串然后将其传入:您必须传入 Show 的内容。当然,String 是 Show,但是如果你给它一个 String,它会在那个 String 上调用 show,并最终用 " 字符包装它!大概是现在您正在传递 Float 值,而库正在呈现它们。您想要的是一种行为类似于 Float 但具有不同 Show 实现的类型。这就是新类型的用途:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype ThreeDigitFloat = TDF Float
  -- cut any of these you don't need
  deriving (Num, Eq, Ord, Floating, RealFloat, Fractional, Real, RealFrac)

instance Show ThreeDigitFloat where
  show (TDF x) = _whateverYouWant

然后您无需使用 Float,只需使用 ThreeDigitFloat,该库将按照您的意图呈现它们。

https://stackoverflow.com/questions/73954239/

相关文章:

go - gcloud 函数部署 go 运行时错误 "undefined: unsafe.Slice

Python - 如何删除以数字开头并包含句点的单词

ruby - 如何在 Ruby 中创建可调用属性

c++ - 如何在 SSE2 中为 8 位和 16 位整数实现 vector 右移和左移?

c# - 在 C# 中将小驼峰命名法转换为 PascalCase?

bash - 使用 sed 删除算术形式

rust - Rust 中的一个可变借用或多个不可变借用……为什么?

python - 在python中打印出两个列表的组合

python - 在代表 python 中大文件的大字符串上加速 re.sub()?

regex - 为什么 Perl 正则表达式不匹配 "\n"和后面的字符?