Ale*_*nko 10 haskell type-families newtype
我想知道为什么Haskell中的未装箱类型有这些限制:
您无法为未装箱类型定义新类型:
newtype Vec = Vec (# Float#, Float# #)
Run Code Online (Sandbox Code Playgroud)
但您可以定义类型synonim:
type Vec = (# Float#, Float# #)
Run Code Online (Sandbox Code Playgroud)类型系列无法返回未装箱类型:
type family Unbox (a :: *) :: # where
Unbox Int = Int#
Unbox Word = Word#
Unbox Float = Float#
Unbox Double = Double#
Unbox Char = Char#
Run Code Online (Sandbox Code Playgroud)这背后有一些根本原因,还是因为没有人要求这个功能?
And*_*ács 10
Haskell中的参数多态性依赖于以下事实:t :: *类型的所有值均匀地表示为指向运行时对象的指针.因此,相同的机器代码适用于多态值的所有实例化.
对比Rust或C++中的多态函数.例如,其中的标识函数仍具有类似的类型forall a. a -> a,但由于不同a类型的值可能具有不同的大小,因此编译器必须为每个实例生成不同的代码.这也意味着我们无法在运行时框中传递多态函数:
data Id = Id (forall a. a -> a)
Run Code Online (Sandbox Code Playgroud)
因为这样的函数必须适用于任意大小的对象.它需要一些额外的基础结构来允许这个功能,例如我们可能要求运行时forall a. a -> a函数采用额外的隐式参数来携带有关值的大小和构造函数/析构函数的信息a.
现在,问题newtype Vec = Vec (# Float#, Float# #)在于即使Vec有类型*,运行时代码期望某些值t :: *无法处理它.它是一个堆栈分配的浮点数,而不是指向Haskell对象的指针,并将其传递给期望Haskell对象的代码会导致段错误或错误.
通常(# a, b #)不一定是指针大小的,因此我们不能将其复制到指针大小的数据字段中.
#由于相关原因,不允许返回类型系列.考虑以下:
type family Foo (a :: *) :: # where
Foo Int = Int#
Foo a = (# Int#, Int# #)
data Box = forall (a :: *). Box (Foo a)
Run Code Online (Sandbox Code Playgroud)
我们Box不是可表示的运行时,因为Foo a不同的a-s 具有不同的大小.通常,多态性#需要为不同的实例化生成不同的代码,例如在Rust中,但这与常规参数多态性相互作用很严重,并且使多态值的运行时表示变得困难,因此GHC不会为此烦恼.
(不是说虽然不可能设计出可用的实现)
| 归档时间: |
|
| 查看次数: |
269 次 |
| 最近记录: |