这些 Haskell 类型是怎么回事?

What’s going on with these Haskell types?

为什么这个函数需要一个整数列表?

Prelude> :t \xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..(length xs)]]
\xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..(length xs)]]
  :: [Int] -> [[Int]]

当我用固定值替换 length xs 时,类型发生变化并且不再那么严格:

Prelude> :t \xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..100]]
\xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..100]]
  :: (Num b, Enum b) => [b] -> [[b]]

我的编译器是

$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.8.4

length 的类型为 Foldable t => t a -> Int,这意味着 length xs 是一个 Int 值。这使得 [1..(length xs)] 成为 [Int] 类型,等等

100,另一方面,不是一个Int文字,而是Num a => a类型的多态文字。这使得 [1..100] 具有类型 Num a => [a],等等

也就是说,length 是唯一在最终类型中强制使用像 Int 这样的具体类型的东西。将其替换为更通用的 100,最终类型也更通用。