我正在尝试编写一个函数
roundedSqrt : Nat -> Nat
roundedSqrt = abs . round . sqrt . fromIntegral
是否有功能
round: Double -> Int
abs : Int -> Nat
或伊德里斯的类似事情?
编辑:
floor : Double -> Int
ceiling : Double -> Int
对于我的用例,对round
都是可接受的替代方案。
答案 0 :(得分:4)
找出问题的一种方法是使用Idris REPL。特别是:search
命令(或其缩写:s
)。
要了解我们需要将sqrt
Double -> Double
类型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}
函数:
Double
不幸的是,它不会使用错误编译:
无法从
Nat
投射到Cast Double Nat
因为标准库中没有cast {to=Nat}
实例(因此Double
不合法)。
作为一种解决方法,我建议执行从Integer
到Nat
到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}
sqrt
rounding towards zero,a.k.a。truncation。
顺便说一下,使用abs
可能不是计算此问题的最佳方法。注意浮点舍入错误,他们可以出乎意料地得到一个一个接一个的结果。由于您的函数类似于integer square root,因此最好实现与此类似的东西。
现在转到floor
,ceiling
,round
和Neg
个功能。
abs
接口使用以下类型定义abs : Neg ty => ty -> ty
:
abs : Int -> Nat
因此,您需要进行一些简单的类型转换才能实现floor : Double -> Double
ceiling : Double -> Double
。
标准Prelude还定义了
Double -> Int
因此,只需要做一点工作,就可以将它们重新转换为round
。
没有标准class MyDict(dict):
def __getitem__(self,key):
value=dict.__getitem__(self,key)
if callable(value):
value=value(self)
return value
mydict=MyDict({'mass':1.0,'volume':0.5})
mydict['density'] = lambda mydict: mydict['mass']/mydict['volume']
print(mydict['density'])
函数,如果您仍然需要它,那么您可以尝试使用Haskell RealFrac
类型类作为示例来实现它。