说我有以下功能:
--count number of an item in a list
count :: (Eq a) => a -> [a] -> Double
count x [] = 0.0
count x (y:ys) = (is x y) + count x ys
和
--returns 1 if items match, else 0
is :: (Eq a) => a -> a -> Double
is x y
| x == y = 1.0
| otherwise = 0.0
和
--compute length of the list
len :: [a] -> Double
len [] = 0.0
len [x] = 1.0
len (x:xs) = 1.0 + len xs
我想使用此方法生成一个生成规范化计数的函数:
--generates frequency of item in list
ncount :: (Eq a) => a -> [a] -> Double
ncount x [] = 0.0
ncount x y = norm * (count x y)
where
norm = 1.0 / len y
我很想知道如何处理这种情况下的签名。 count
有签名(Eq a) => a -> [a] -> Double
,但ncount
也应该有这个签名吗?一方面,如果调用a
时Eq
不在ncount
,则count
的后续调用将失败。另一方面ncount
从不测试平等。
抱歉,遗漏了is
和len
:w
答案 0 :(得分:2)
一般来说,最好给每个函数赋予它可以接受的最多态(即最全面)类型的签名。总有可能在其他地方找到该功能的另一种用途。
我发现它非常有用:
:t
命令向GHCi询问它认为类型签名应该是什么。 这完成了两件事。首先,GHCi可能会提出比我最初编写函数更广泛的类型签名。通常,更广泛的类型签名更好。其次,它验证函数正在执行我打算执行的操作。这有时突出了我实现中的一个错误。
当然,有时候较窄的签名更合适。尽管可以针对各种类型执行计算,但是对于某些类型而言它可能“有意义”。但在实践中,我很少发现情况如此。另一个原因是性能问题,正如Satvik所指出的那样。