GHC没有推断出我想要的方式:-(

时间:2011-08-21 04:07:24

标签: haskell

chainQuery :: (Enum a, Integral a, Ord b) => a -> b -> [c]
chainQuery n min = map length $ filter beatingLength $ map chain [1..n]
  where
    beatingLength :: [a] -> Bool
    beatingLength xs = length xs > min
    chain :: (Integral a) => a -> [a]
    chain n
      | n <= 1 = [n]
      | even n = n:(chain $ div n 2)
      | otherwise = n:(chain $ n * 3 + 1)
  1. 在上面的代码示例中,为什么GHC不能通过查看长度的类型定义来推断'c'是否为Int?

  2. 为什么GHC需要知道关于'b'的任何事情而不是它是Ord?

  3. 有没有更好的方法来编写此功能?

1 个答案:

答案 0 :(得分:9)

  1. GHC能够推断[Int]作为函数的结果类型。问题是你在你的类型签名中声称它应该更多多态,结果可能是任何类型的列表,这是没有意义的,因为返回值来自{ {1}}所以它必须有map length类型。这就是GHC在说[Int]时抱怨的。

  2. 您正在将Could not deduce (c ~ Int)min进行比较。大于运算符的类型为length xs,这意味着双方必须是同一类型。 (>) :: (Ord a) => a -> a -> Bool的类型为length xs,因此强制Int也为min

  3. 可能。例如,您可以在进行过滤之前映射长度。这样可以轻松使用运算符部分而不是Int函数。您还可以移动括号以保存beatingLength的使用,以使代码更整洁。

    $
  4. 作为参考,解决此类问题的最简单方法是删除类型签名,并查看使用chainQuery n min = filter (> min) $ map (length . chain) [1..n] where chain n | n <= 1 = [1] | even n = n : chain (n `div` 2) | otherwise = n : chain (3*n + 1) 命令在GHCi中推断出的类型。在这种情况下,推断类型是

    :t