gpt4 book ai didi

haskell - :sprint for polymorphic values?

转载 作者:行者123 更新时间:2023-12-02 09:53:04 27 4
gpt4 key购买 nike

我想知道为什么 :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 的类型在第一种情况下是多态的但在第二种情况下不是有关?我想知道内部发生了什么。

最佳答案

要点是,对于多态 xs,它具有以下形式的类型

xs :: Num a => [a]

底层的类型类实际上只是函数,它们采用 GHC 自动填充的额外参数,其中包含类型类函数的记录。所以你可以认为 xs 具有类型

xs :: NumDict a -> [a]

所以当你运行时

Prelude> length xs

它必须为a选择一些值,并找到相应的NumDict值。 IIRC 它将用 Integer 填充它,因此您实际上是在调用函数并检查结果列表的长度。

当您使用 :sprint xs 时,您将再次填充该参数,这次使用新的类型变量。但关键是,您得到了一个完全不同的列表,您给了它一个不同的 NumDict,因此当您之前调用 length 时,它不会以任何方式强制。

这与显式单态列表非常不同,因为那里实际上只有一个列表,只有一个要强制的值,因此当您调用 length 时,它会强制它用于 xs 的所有 future 使用.

为了让这一点更清楚,请考虑代码

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

这实际上就是类型类的本质,GHC 会自动为我们填写第一个 Smash a 参数。现在您的第一个示例类似于 join,当我们将其应用于不同类型时,我们无法对输出进行任何假设,但您的第二个示例更像

join' :: [Int] -> Int
join' = join intSmash

关于haskell - :sprint for polymorphic values?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21518584/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com