:sprint的多态值?

Eri*_*ikR 13 haskell ghci thunk monomorphism-restriction

我想知道为什么在这种情况下的:sprint报告xs = _:

Prelude> xs = map (+1) [1..10]
Prelude> length xs
10
Prelude> :sprint xs
xs = _
Run Code Online (Sandbox Code Playgroud)

但在这种情况下不是:

Prelude> xs = map (+1) [1..10] :: [Int]
Prelude> length xs
10
Prelude> :sprint xs
xs = [_,_,_,_,_,_,_,_,_,_]
Run Code Online (Sandbox Code Playgroud)

注:我正在ghci-XNoMonomorphismRestriction.是否与xs第一种情况下的多态性类型有关,而在第二种情况下不是多态性的事实?我想知道内部发生了什么.

Dan*_*zer 10

要点是具有多态性的xs它具有一种形式

xs :: Num a => [a]
Run Code Online (Sandbox Code Playgroud)

引擎盖下的类型实际上只是函数,它们需要额外的参数,GHC自动填充包含类型类函数的记录.所以你可以考虑xs拥有这种类型

xs :: NumDict a -> [a]
Run Code Online (Sandbox Code Playgroud)

所以当你跑步

Prelude> length xs
Run Code Online (Sandbox Code Playgroud)

它必须选择一些值a,并找到相应的NumDict值.IIRC它将填充它Integer,所以你实际上调用一个函数并检查结果列表的长度.

当你那时:sprint xs,你再次填充那个参数,这次是一个新的类型变量.但重点是你得到一个完全不同的列表,你给它一个不同的,NumDict所以当你length之前打电话时,它不会以任何方式强迫它.

这与明确的单态列表非常不同,因为那里只有一个列表,只有一个值强制这样,当你调用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
Run Code Online (Sandbox Code Playgroud)

这就是真正的类型类,GHC会自动Smash a为我们填写第一个参数.现在你的第一个例子是join,我们不能对输出将是什么应用于不同类型做出任何假设,但你的第二个例子更像是

join' :: [Int] -> Int
join' = join intSmash
Run Code Online (Sandbox Code Playgroud)