首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多态值的sprint?

多态值的sprint?
EN

Stack Overflow用户
提问于 2014-02-03 01:41:02
回答 1查看 546关注 0票数 14

我想知道为什么:sprint在本例中报告xs = _

代码语言:javascript
复制
Prelude> xs = map (+1) [1..10]
Prelude> length xs
10
Prelude> :sprint xs
xs = _

但在这种情况下却不是这样:

代码语言:javascript
复制
Prelude> xs = map (+1) [1..10] :: [Int]
Prelude> length xs
10
Prelude> :sprint xs
xs = [_,_,_,_,_,_,_,_,_,_]

注意:我正在使用ghci运行-XNoMonomorphismRestriction。这与xs的类型在第一种情况下是多态而在第二种情况下不是多态这一事实有关吗?我想知道内部是怎么回事。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-03 05:52:31

其要点是,对于多态xs,它具有一种形式

代码语言:javascript
复制
xs :: Num a => [a]

引擎盖下的类型类实际上只是函数,它们采取额外的参数,GHC自动填充包含类型类函数记录的GHC。所以你可以想象xs有这样的类型

代码语言:javascript
复制
xs :: NumDict a -> [a]

所以当你跑的时候

代码语言:javascript
复制
Prelude> length xs

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

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

这与显式单形列表是非常不同的,因为那里实际上只有一个列表,只有一个值可以强制执行,所以当您调用length时,它强制它用于xs的所有未来用途。

为了使这一点更清楚,请考虑以下代码

代码语言:javascript
复制
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,当我们将其应用于不同的类型时,我们不能对输出进行任何假设,但是第二个示例更像是

代码语言:javascript
复制
join' :: [Int] -> Int
join' = join intSmash
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21518584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档