Это значение squares
потенциально полиморфно:
Prelude> :t [ x ** 2 | x <- [1 ..] ]
[ x ** 2 | x <- [1 ..] ] :: (Floating t, Enum t) => [t]
AFAIK, будет ли он пересчитан (в GHC) или нет, зависит от того, имеет ли значение верхнего уровня squares
полиморфный тип. Я считаю, что GHC не запоминает полиморфные значения, включающие классы типов (функции от типов к значениям), так же, как он не запоминает обычные функции (функции от значений к значениям).
Это означает, что если вы определите squares
как
squares :: [Double]
squares = [ x ** 2 | x <- [1 ..] ]
, тогда squares
будет вычисляться только один раз, в то время как вы определяете его как
squares :: (Floating t, Enum t) => [t]
squares = [ x ** 2 | x <- [1 ..] ]
тогда он, вероятно, будет вычисляться при каждом использовании, даже если он используется несколько раз в одном и том же типе. (Я не проверял это, хотя, и возможно, что GHC, если он видит несколько вариантов использования squares :: [Double]
, может специализировать значение squares
для этого типа и разделять полученное значение.) Конечно, если используется squares
для нескольких различных типов, таких как squares :: [Double]
и squares :: [Float]
, он будет пересчитан.
Если вы не дадите никакой сигнатуры типа для squares
, то к ней будет применено ограничение мономорфизма , если оно не отключено. В результате squares
будет присвоен мономорфный тип, выведенный из остальной части вашей программы (или в соответствии с правилами по умолчанию). Цель ограничения мономорфизма состоит в том, чтобы гарантировать, что значения, которые выглядят так, как будто они будут оцениваться только один раз, например, squares
, действительно будут оцениваться только один раз.