首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一个任意的名词怎么能包含任何其他的数字类型?

一个任意的名词怎么能包含任何其他的数字类型?
EN

Stack Overflow用户
提问于 2015-10-04 18:00:40
回答 1查看 147关注 0票数 2

我刚从Haskell开始,我想先做一个随机的图像发生器。我环顾四周,发现了JuicyPixels,它提供了一个名为generateImage的简洁函数。他们给出的例子似乎行不通。

他们的例子:

代码语言:javascript
运行
复制
imageCreator :: String -> IO ()
imageCreator path = writePng path $ generateImage pixelRenderer 250 300
   where pixelRenderer x y = PixelRGB8 x y 128

当我尝试这样做时,我得到generateImage需要一个Int -> Int -> PixelRGB8,而pixelRenderer是类型为Pixel8 -> Pixel8 -> PixelRGB8的。PixelRGB8Pixel8 -> Pixel8 -> Pixel8 -> PixelRGB8类型,因此pixelRenderer正在进行某种类型推断以确定xyPixel8类型,这是有意义的。如果我定义了一个类型签名,断言它们是Int类型(因此该函数被generateImage接受),PixelRGB8会抱怨它需要Pixel8s,而不是Ints

Pixel8只是Word8的一个类型别名。拔了头发之后,我发现将Int转换为Word8的方法是使用fromIntegral

fromIntegral的类型签名是(Integral a, Num b) => a -> b。在我看来,这个函数实际上并不知道要将它转换为什么,所以它将转换为非常通用的Num类。所以从理论上讲,它的输出是符合类型类Num的任何类型的变量(如果我在这里弄错了--据我理解,类有点像“接口”,其中类型更像OOP中的类/原语)。如果我给变量赋值

代码语言:javascript
运行
复制
let n = fromIntegral 5
:t n -- n :: Num b => b

所以我想知道..。什么是“b”?我可以将这个变量作为任何变量使用,并且它将隐式转换为任何数字类型,就像它看起来的那样。它不仅将隐式转换为Word8,还将隐式转换为Pixel8,这意味着根据上下文,fromPixel有效地从(据我理解) (Integral a, Num b) => a -> b转换为(Integral a) => a -> Pixel8

有人能确切地说明一下这里发生了什么吗?为什么我可以使用通用Num作为符合Num的任何类型,无论是机械的还是“道德的”?我不明白隐式转换是如何实现的(如果要创建自己的类,我觉得需要添加显式转换函数)。我也不知道为什么会这样;在这里,我可以使用非常不安全的类型,并将其隐式地转换为任何其他类型。(例如,如果我将fromIntegral 50000隐式转换为Word8,它将被转换为Word8)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-04 18:15:24

类型类(如Num )的一个常见实现是字典传递。粗略地说,当编译器看到类似于

代码语言:javascript
运行
复制
f :: Num a => a -> a
f x = x + 2

它把它转化成某种东西

代码语言:javascript
运行
复制
f :: (Integer -> a, a -> a -> a) -> a -> a
  -- ^-- the "dictionary"
f (dictFromInteger, dictPlus) x = dictPlus x (dictFromInteger 2)

后者基本上是这样说的:“为您的类型Num传递这些类a方法的实现,我将使用它们为您生成一个函数a -> a”。

像您的n :: Num b => b这样的值没有什么不同。它们被编译成如下所示

代码语言:javascript
运行
复制
n :: (Integer -> b) -> b
n dictFromInteger = dictFromInteger 5   -- roughly

正如您所看到的,这会将看似无辜的整数文本转换为函数,这会(而且确实)影响性能。但是,在许多情况下,编译器可以意识到实际上不需要完整的多态版本,并删除所有字典。

例如,如果编写f 3f需要Int,则可以在编译时转换“多态”3。因此,类型推断可以帮助优化阶段(用户编写的类型注释在这里可以提供很大的帮助)。此外,还可以手动触发其他一些优化,例如使用GHC SPECIALIZE实用程序。最后,可怕的单态限制在翻译后很难强迫非函数保持非函数,代价是多态性的损失。然而,MR现在被认为是有害的,因为它会在某些情况下造成令人费解的类型错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32936592

复制
相关文章

相似问题

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