Der*_*urn 4 double haskell types integer
假设我正在编写一个获取整数列表的函数,并仅返回列表中小于5.2的整数.我可能会这样做:
belowThreshold = filter (< 5.2)
Run Code Online (Sandbox Code Playgroud)
够容易吧?但是现在我想将这个函数限制为只使用类型为[Int]的输入列表,这是出于我自己的设计原因.这似乎是一个合理的要求.唉,没有.一个声明,限制类型如下:
belowThreshold :: [Integer] -> [Integer]
belowThreshold = filter (< 5.2)
Run Code Online (Sandbox Code Playgroud)
导致类型错误.那么这里的故事是什么?为什么做过滤器(<5.2)似乎将我的输入列表转换为双打?如何创建仅接受整数列表且仅返回整数列表的此函数的版本?为什么类型系统讨厌我?
在添加annoatation之前,请检查ghci中推断的belowThreshold类型:
> :t belowThreshold
belowThreshold :: [Double] -> [Double]
Run Code Online (Sandbox Code Playgroud)
Num a => [a] -> [a]当你说"约束这个功能"时,听起来就像你期望的那样.实际上,在添加[Integer] -> [Integer]注释时,您正在更改函数的类型.
要使其工作,请使用显式转换:
belowThreshold = filter ((< 5.2) . fromIntegral)
Run Code Online (Sandbox Code Playgroud)
现在belowThreshold :: [Integer] -> [Integer]喜欢你想要的.但是在与5.2比较之前,整数被转换为双精度数.
那你为什么需要转换呢?该类型的错误可能误导你:整数列表没有被转换成双打通过对比5.2,真正的问题是,只有双打可以与双打,所以你必须通过双打的名单belowThreshold.Haskell没有隐式转换,甚至没有数字之间的转换.如果您想要转换,您必须自己编写.
我想将此函数限制为仅使用类型为[Int]的输入列表,这是出于我自己的设计原因.这似乎是一个合理的要求.
那么,从类型系统的角度来看,没有.这是合理的代码吗?
'c' < "foo"
Run Code Online (Sandbox Code Playgroud)
那这个呢?
12 < "bar"
Run Code Online (Sandbox Code Playgroud)
所有这些值都是实例Ord,但您不能与它们一起使用(<).Haskell没有隐式转换.所以,即使两个值的两个实例Num,以及Ord,你将无法与他们相比(<),如果他们是不同类型的.