更正组合函数的签名

时间:2013-08-26 13:33:14

标签: haskell types signature

说我有以下功能:

--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也应该有这个签名吗?一方面,如果调用aEq不在ncount,则count的后续调用将失败。另一方面ncount从不测试平等。

抱歉,遗漏了islen:w

1 个答案:

答案 0 :(得分:2)

一般来说,最好给每个函数赋予它可以接受的最多态(即最全面)类型的签名。总有可能在其他地方找到该功能的另一种用途。

我发现它非常有用:

  1. 对没有类型签名的函数进行编码。
  2. 决定认为应该拥有的签名类型。
  3. 使用:t命令向GHCi询问它认为类型签名应该是什么。
  4. 比较(2)与(3)。
  5. 这完成了两件事。首先,GHCi可能会提出比我最初编写函数更广泛的类型签名。通常,更广泛的类型签名更好。其次,它验证函数正在执行我打算执行的操作。这有时突出了我实现中的一个错误。

    当然,有时候较窄的签名更合适。尽管可以针对各种类型执行计算,但是对于某些类型而言它可能“有意义”。但在实践中,我很少发现情况如此。另一个原因是性能问题,正如Satvik所指出的那样。