Home > Blockchain >  What’s going on with these Haskell types?
What’s going on with these Haskell types?

Time:12-22

Why does this function require a list of integers?

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]]

When I replace length xs with a fixed value, the type changes and isn’t that strict anymore:

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]]

My compiler is

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

CodePudding user response:

length has type Foldable t => t a -> Int, which means length xs is specifically an Int value. That makes [1..(length xs)] be of type [Int], etc.

100, on the other hand, is not an Int literal, but a polymorphic literal of type Num a => a. That makes [1..100] have type Num a => [a], etc.

Which is to say, length is the only thing that's forcing a concrete type like Int in the final type. Replace that with the more general 100, and the final type is more general as well.

  • Related