haskell - 了解单态与多态核心表达式
问题描述
我想了解如何将简单的算术表达式编译到 GHC 9.0.1 Core
为此,我隔离了相同的声明,
f = \x y -> sqrt x + y
并将其编译为两种不同的类型:
f :: Double -> Double -> Double
f :: Floating a => a -> a -> a
导致这些非常不同的野兽:
\ (x [Dmd=<S,1*U(U)>] :: Double) (y [Dmd=<S,1*U(U)>] :: Double) ->
case x of { D# x ->
case y of { D# y -> D# (+## (sqrtDouble# x) y) }
}
在单态的情况下和
\ (@a)
($dFloating_a22t [Dmd=<S(S(S(C(C(S))LLLLLL)LLL)LLLLLLLLLLLLLLLLLLLLLL),U(1*U(1*U(1*C1(C1(U)),A,A,A,A,A,A),A,A,A),A,A,A,1*C1(U),A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A)>]
:: Floating a)
(eta_B0 :: a)
(eta_B1 :: a) ->
+ @a
($p1Fractional @a ($p1Floating @a $dFloating_a22t))
(sqrt @a $dFloating_a22t eta_B0)
eta_B1
在多态之一。
除了需要单独提出问题的需求/严格性注释(这些Dmd=...
东西)之外,我很想了解这两个结果表达式的不同形状。在单态情况下,我们进行了嵌套大小写匹配,但在另一种情况下,我们只看到使用类型变量 ( @a
) 和约束 ($p1Fractional
等)注释的运算符。
我想我应该补充一点,上面的输出是通过在预先存在的 CoreToDo 列表的最后运行的自定义插件传递获得的,所以在脱糖等之后(这就是我对这个主题的全部了解)
是否存在这两个编译版本在结构上相同的 GHC 阶段?
解决方案
在内部,aFloat
是一个数据构造函数,其中一个字段包含Float#
底层机器格式的原语(因此是 32 位字)。
data Float = MkFloat Float#
这是一个加框表示,因此 aFloat
也可能是一个 thunk。表达式的作用是case
评估任何 thunk 然后访问底层机器Float#
。
因此,您的函数Float -> Float -> Float
在简化后编译为与参数匹配的函数,并对基础值执行原始操作。
类型类被编译成字典。
class Floating a where
sqrt :: a -> a
...
-- becomes a record --
data Floating a = MkFloating {
sqrt :: a -> a,
... }
多态函数成为字典传递函数
Floating a => a -> a -> a
-- becomes --
Floating a -> a -> a -> a
方法调用成为字段访问:
sqrt x
-- becomes --
sqrt floatingDict x
-- where floatingDict :: Floating a is constructed from dictionary parameters in scope and from instances (which are compiled to dictionaries or functions on dictionaries)
(注意:这在某种程度上是特定于 GHC 的,其他编译器虽然很少见,但可能会做不同的事情。)
是否存在这两个编译版本在结构上相同的 GHC 阶段?
不,他们为什么会这样?
推荐阅读
- jquery - wordpress:AppMe 主题在 macOS 中不播放背景视频
- c++ - 我可以存储指向转发声明的类/结构的指针吗?
- mongodb - MongoDB中的聚合总和
- fortran - gfortran -fopenmp 导致分段错误
- html - CSS按钮滑动过渡效果问题
- architecture - Xcode 12 Apple M1 arm64 - 可设计错误:“错误的架构”
- excel - 当我已经在变量中设置文件名和路径时如何关闭工作簿
- python - Tensorflow:梯度在训练过程中突然变成了 NaN
- xml - 如何删除 PostgreSQL 中的 XML 属性?
- angular - 从 @ 开始的 Angular 模块