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)
| 归档时间: |
|
| 查看次数: |
452 次 |
| 最近记录: |