:多态值的冲刺?
我想知道为什么:sprint报告xs = _在这种情况下: 
 Prelude> xs = map (+1) [1..10] Prelude> length xs 10 Prelude> :sprint xs xs = _ 
但不是在这种情况下:
 Prelude> xs = map (+1) [1..10] :: [Int] Prelude> length xs 10 Prelude> :sprint xs xs = [_,_,_,_,_,_,_,_,_,_] 
 注意:我用-XNoMonomorphismRestriction运行ghci 。 这是否与第一种情况下的xstypes是多态有关,而不是第二种情况呢? 我想知道内部发生了什么。 
 要点是,与多态xs它有一个forms的types 
 xs :: Num a => [a] 
 引擎盖下的types实际上只是函数,他们需要一个额外的参数,GHC自动填充包含typeclasses函数的logging。 所以你可以认为xs是types的 
 xs :: NumDict a -> [a] 
所以当你跑步
 Prelude> length xs 
 它必须为aselect一些值,并find相应的NumDict值。  IIRC它会用Integer填充它,所以你实际上正在调用一个函数,并检查结果列表的长度。 
 当你那么:sprint xs ,你再一次填充这个参数,这次用一个新鲜的typesvariables。 但重要的是,你得到了一个完全不同的列表,你给它一个不同的NumDict所以当你以前调用length时不会被强迫。 
 这与明确的单态列表是非常不同的,因为实际上只有一个列表,所以只有一个值是强制的,所以当你调用长度的时候,它会强制所有将来使用的xs 。 
为了使这个更清楚一些,考虑一下代码
 data Smash a = Smash { smash :: a -> a -> a } -- ^ Think of Monoids intSmash :: Smash Int intSmash = Smash (+) listSmash :: Smash [a] listPlus = Smash (++) join :: Smash a -> [a] -> a join (Smash s) xs = foldl1' s xs 
 这实际上是什么types的types是在引擎盖下,GHC会自动填写第一个Smash a我们Smash a论据。 现在你的第一个例子就像join ,我们不能做任何假设输出将是什么,因为我们将其应用于不同的types,但你的第二个例子更像 
 join' :: [Int] -> Int join' = join intSmash