Idris 中的圆形和 abs 函数

Round and abs function in Idris

我正在尝试编写一个函数

roundedSqrt : Nat -> Nat
roundedSqrt = abs . round . sqrt . fromIntegral

是否有函数

round: Double -> Int
abs : Int -> Nat

或 Idris 中的类似内容?

编辑:

floor : Double -> Int
ceiling : Double -> Int
对于我的用例,

都是 round 的可接受替代方案。

找出您要问的内容的一种方法是使用 Idris REPL。特别是 :search 命令(或其缩写 :s)。 为了发现我们需要什么才能将 Double -> Double 类型的 sqrt 应用到 Nat,我们可以尝试这样的事情:

Idris> :s Nat -> Double
< Prelude.Cast.cast : Cast from to => from -> to
Perform a cast operation.

使用 cast 函数,我们可以编写以下版本:

roundedSqrtDoesntCompile : Nat -> Nat
roundedSqrtDoesntCompile = cast {to=Nat} . sqrt . cast {to=Double}

不幸的是,它不会编译错误:

Can't cast from Double to Nat

因为标准库中没有Cast Double Nat实例(所以cast {to=Nat}是不合法的)。

作为解决方法,我建议执行从 DoubleIntegerNat:

的双重(无双关语意)转换
roundedSqrt : Nat -> Nat
roundedSqrt = cast {to=Nat} . cast {to=Integer} . sqrt . cast {to=Double}

可以写得更简洁

roundedSqrt : Nat -> Nat
roundedSqrt = cast . cast {to=Integer} . sqrt . cast

cast {to=Integer} rounding towards zero, a.k.a. truncation.

顺便说一下,使用 sqrt 可能不是最好的计算方法。当心浮点舍入错误,它们可能会意外地让您得到一个差一的结果。由于您的函数类似于 integer square root,因此最好实现接近于此的功能。


现在介绍 absfloorceilinground 函数。

Neg 接口定义 abs 具有以下类型:

abs : Neg ty => ty -> ty

所以你需要做一些简单的类型转换来实现 abs : Int -> Nat

标准的 Prelude 也定义了

floor : Double -> Double
ceiling : Double -> Double

所以,再做一点工作就可以将它们重铸成 Double -> Int

没有标准的 round 函数,如果您仍然需要它,那么您可以尝试使用 Haskell RealFrac 类型类作为示例来实现它。