:多态值的冲刺?
我想知道为什么: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
。 这是否与第一种情况下的xs
types是多态有关,而不是第二种情况呢? 我想知道内部发生了什么。
要点是,与多态xs
它有一个forms的types
xs :: Num a => [a]
引擎盖下的types实际上只是函数,他们需要一个额外的参数,GHC自动填充包含typeclasses函数的logging。 所以你可以认为xs
是types的
xs :: NumDict a -> [a]
所以当你跑步
Prelude> length xs
它必须为a
select一些值,并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