这些 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
,最终类型也更通用。
为什么这个函数需要一个整数列表?
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
,最终类型也更通用。