为什么这个 haskell 类型签名不起作用?
Why doesn't this haskell type signature work?
这里是 haskell 的新人。我正在尝试更好地编写类型签名,而这个简单的签名不想工作。我想知道为什么:
average :: Num a => [a] -> a
average ns = sum ns `div` length ns
平均应该取任何数字和 return 一些数字。但是我收到错误
test.hs 11:27:
Couldn't match expected type 'a' with actual type 'Int'
'a' is a rigid type variable bound by
the type signature for average :: Num a => [a] -> a
at test.hs:10:12
Relevant bindings include
ns:: [a] (bound at test.hs:11:9)
average :: [a] -> a (bound at test.hs:11:1)
In the second argument of 'div' namely 'length ns'
In the expression: sum ns `div ` length ns
好像是说长度没有达到预期。谁能帮忙?
好的,这会起作用:
average :: Integral a => [a] -> a
average ns = sum ns `div` (fromIntegral $ length ns)
请注意 div :: Integral a => a -> a -> a
所以你需要 Integral a
而不是 Num a
(没有除法)
而且因为 length
会 return 一个 Int
所以你需要 fromIntegral
来解决它。
div
的类型是Integral a => a -> a -> a
,这意味着它的两个参数必须是同一类型。在这种情况下,第二个参数始终是 Int
类型(length
的结果),但第一个参数是 a
.
类型
此外,您正在尝试编写适用于任何类型 Num
的函数,但 div
仅适用于整数类型。如果你想支持 "averaging" 整数值列表(结果也被四舍五入为整数),你可以这样做:
average :: Integral a => [a] -> a
average ns = sum ns `div` fromIntegral (length ns)
fromIntegral
会将 Int
长度转换为 a
的任何整数类型(可能是 Int
,或类似 Integer
的类型)。
为避免舍入错误,您需要对小数类型使用小数除法:
average :: Fractional a => [a] -> a
average ns = sum ns / fromIntegral (length ns)
其他答案很好地突出了 Num
与 Integral
调用 length
后使用强制转换的提议的问题。或者,您可以使用 Data.List
:
中的 genericLength
import Data.List
average :: Integral a => [a] -> a
average ns = sum ns `div` genericLength ns
这里是 haskell 的新人。我正在尝试更好地编写类型签名,而这个简单的签名不想工作。我想知道为什么:
average :: Num a => [a] -> a
average ns = sum ns `div` length ns
平均应该取任何数字和 return 一些数字。但是我收到错误
test.hs 11:27:
Couldn't match expected type 'a' with actual type 'Int'
'a' is a rigid type variable bound by
the type signature for average :: Num a => [a] -> a
at test.hs:10:12
Relevant bindings include
ns:: [a] (bound at test.hs:11:9)
average :: [a] -> a (bound at test.hs:11:1)
In the second argument of 'div' namely 'length ns'
In the expression: sum ns `div ` length ns
好像是说长度没有达到预期。谁能帮忙?
好的,这会起作用:
average :: Integral a => [a] -> a
average ns = sum ns `div` (fromIntegral $ length ns)
请注意 div :: Integral a => a -> a -> a
所以你需要 Integral a
而不是 Num a
(没有除法)
而且因为 length
会 return 一个 Int
所以你需要 fromIntegral
来解决它。
div
的类型是Integral a => a -> a -> a
,这意味着它的两个参数必须是同一类型。在这种情况下,第二个参数始终是 Int
类型(length
的结果),但第一个参数是 a
.
此外,您正在尝试编写适用于任何类型 Num
的函数,但 div
仅适用于整数类型。如果你想支持 "averaging" 整数值列表(结果也被四舍五入为整数),你可以这样做:
average :: Integral a => [a] -> a
average ns = sum ns `div` fromIntegral (length ns)
fromIntegral
会将 Int
长度转换为 a
的任何整数类型(可能是 Int
,或类似 Integer
的类型)。
为避免舍入错误,您需要对小数类型使用小数除法:
average :: Fractional a => [a] -> a
average ns = sum ns / fromIntegral (length ns)
其他答案很好地突出了 Num
与 Integral
调用 length
后使用强制转换的提议的问题。或者,您可以使用 Data.List
:
genericLength
import Data.List
average :: Integral a => [a] -> a
average ns = sum ns `div` genericLength ns