小编cut*_*lus的帖子

为什么C++的void类型只是半心半意的单位类型?

C++的void类型并非无人居住.问题在于,虽然它只有一个居民,非常像ML类语言中的Unit类型(又名()),居民不能被命名或传递为普通价值.例如,以下代码无法编译:

void foo(void a) { return; }
void bar() { foo(foo()); }
Run Code Online (Sandbox Code Playgroud)

而等效的(比方说)Rust代码编译得很好:

fn foo(a : ()) { return; }
fn bar() { foo(foo(())); }
Run Code Online (Sandbox Code Playgroud)

实际上,void就像一种unit类型,但只是半心半意.为什么会这样?

C++标准是否明确声明无法创建类型的值void?如果是,这个决定背后的理由是什么?如果没有,为什么上面的代码不能编译?

如果是一些向后兼容性相关的原因,请举一个代码示例.

要清楚,我不是在寻找解决问题的方法(例如使用空结构/类).我想知道现状背后的历史原因.

编辑:我稍微改变了代码示例中的语法,以明确我没有试图劫持现有的语法void foo(void)(因此,一些注释可能已过时).这个问题背后的主要动机是"为什么类型系统不像X",而不是 "为什么这一部分语法不像我喜欢的那样".如果你正在写一个关于打破向后兼容性的答案,请记住这一点.

c++ types

10
推荐指数
1
解决办法
289
查看次数

多态递归的应用

通过单态化(仅单态化)在语言中实现多态性的一个限制是你失去了支持多态递归的能力(例如参见rust-lang #4287).

有哪些引人注目的用例支持编程语言中的多态递归?我一直在努力寻找使用它的库/概念,到目前为止我遇到过一个例子:

  1. 在"命名问题"中,我们希望同时具有(a)快速捕获避免替换和(b)快速alpha等价检查,还有绑定库(此处有更详细的解释).在为函数式编程语言编写编译器时,这两个属性都是可取的.

为了防止这个问题过于宽泛,我正在寻找其他程序/图书馆/研究论文,它们将多态递归的应用呈现给传统的计算机科学问题,例如那些编写编译器的问题.

我不想要的事情的例子:

  1. 回答显示如何使用多态递归从类别理论中编码X,除非它们演示了编码X如何有利于解决Y符合上述标准的问题.

  2. 小玩具示例,表明你可以用多态递归做X,但你不能没有它.

polymorphism recursion haskell

9
推荐指数
2
解决办法
384
查看次数

为什么Rust有"Never"原始类型?

Rust的std::process::exit类型

pub fn exit(code: i32) -> !
Run Code Online (Sandbox Code Playgroud)

哪里!"从不" 原始类型.

为什么Rust需要特殊类型呢?

将其与Haskell进行比较,其类型System.Exit.exitWith

exitWith :: forall a. Int -> a
Run Code Online (Sandbox Code Playgroud)

相应的Rust签名将是

pub fn exit<T>(code: i32) -> T
Run Code Online (Sandbox Code Playgroud)

没有必要将此函数单独化为不同T的函数,因为a T从未实现,因此编译仍然可以工作.

types rust

8
推荐指数
1
解决办法
455
查看次数

OCaml如何在运行时表示惰性值?

这一在现实世界中OCaml中描述了不同数据类型的运行时内存布局。但是,没有关于惰性值的讨论。

  • 如何lazy_t实现,即它的运行时表示形式是什么以及编译器内置的主要操作是什么?链接到源代码将不胜感激。我查看了CamlinternalLazy模块,但是仅基于对Obj模块中函数的调用,似乎很难解读实际的表示形式。
  • 有人可以提供对表示/操作所做的更改的摘要,以使其对于OCaml多核项目而言是线程安全的吗?这个提交似乎是实现的提交,但是对于我来说,作为局外人来说似乎有点不透明。

注意:此问题 OCaml编译器/运行时有关。据我所知,有如何偷懒值应该由没有实施标准规范 ocaml的编译器/运行。

ocaml lazy-evaluation memory-layout data-representation

8
推荐指数
1
解决办法
178
查看次数

Unicode代码点和Unicode标量之间有什么区别?

在很多情况下,我看到两者在看似可以互换使用 - 它们是相同还是不同?这似乎也取决于语言是在谈论UTF-8(例如Rust)还是UTF-16(例如Java/Haskell).代码点/标量的区别是否依赖于编码方案?

unicode

6
推荐指数
1
解决办法
847
查看次数

使用Bound与多个类型变量进行抽象

我一直在试用绑定包 - 你可以尝试使用的一个玩具示例是System F.与包文档中的示例不同,它包含一个由lambda绑定的变量的类型参数,System F将有两个类型参数,一个用于普通变量(由普通的lambda抽象绑定),一个用于类型变量(由类型抽象绑定).

我不太明白如何使用这个包,但是看一下这些例子,我得到的印象是我应该从编写Monad表达式类型的实例开始.然而,我遇到了麻烦,因为我无法想出具体的东西并且"显然是正确的"(即通过检查看起来直观正确).到目前为止我有

{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE LambdaCase #-}

module SystemF where

import Bound
import Control.Monad
import Data.Bifunctor

-- e ::= x | ?x : ?. e | e1 e2 | ?X. e | e [?]
-- t denotes type variables, e denotes expression variables
data Exp t e
  = Var e
  | Lam (Scope () (Exp t) e)
  | App (Exp t …
Run Code Online (Sandbox Code Playgroud)

monads haskell

6
推荐指数
1
解决办法
102
查看次数

show wrt转义字符的语义

考虑以下示例(?>= ghci,$= shell):

?> writeFile "d" $ show "d"
$ cat d
"d"

?> writeFile "d" "d"
$ cat d
d

?> writeFile "backslash" $ show "\\"
$ cat backslash
"\\"

?> writeFile "backslash" "\\"
$ cat backslash
\

?> writeFile "cat" $ show "" -- U+1F408
$ cat cat
"\128008"

?> writeFile "cat" ""
$ cat cat

Run Code Online (Sandbox Code Playgroud)

我理解另一种方式"\128008"只是""在Haskell源代码中表示的另一种方式 .我的问题是:为什么""示例的行为类似于反斜杠而不是像"d"?既然它是一个可打印的角色,它不应该像一个字母吗?

更一般地说,确定字符是显示为可打印字符还是转义码的规则是什么?我查看 了Haskell 2010语言报告中的第6.3节,但没有指定确切的行为.

haskell ghc

4
推荐指数
1
解决办法
106
查看次数

Haskell运行时如何区分指针和未装箱的字大小值?

在64位平台上,int由于指针标记,OCaml的类型为63位.这允许整数被打开,并且仍然可以在运行时与指针区分开来,从而实现精确的GC.IIRC,GHC RTS中的GC也是精确的,但GHC的Int是64位,它们可以是未装箱的.如果是这种情况,那么运行时系统如何区分Ints和指针?看来,区分其他未装箱的字大小值和指针也会产生同样的问题.

garbage-collection haskell ghc

4
推荐指数
2
解决办法
80
查看次数

什么时候延长 Arenas 引用的生命周期是安全的?

我有一个使用的结构Arena

struct Foo<'f> {
    a: Arena<u64>, // from the typed-arena crate
    v: Vec<&'f u64>,
}
Run Code Online (Sandbox Code Playgroud)

只要引用的生命周期受主结构体生命周期的约束,延长竞技场引用的生命周期是否安全?

impl<'f> Foo<'f> {
    pub fn bar(&mut self, n: u64) -> Option<&'f u64> {
        if n == 0 {
            None
        } else {
            let n_ref = unsafe { std::mem::transmute(self.a.alloc(n)) };
            Some(n_ref)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多背景信息,请参阅此Reddit 评论

unsafe lifetime rust

2
推荐指数
1
解决办法
123
查看次数

Rust ABI对枚举紧凑性有什么保证?

据我所知,Rust ABI不稳定.但是,Rust编译器当前执行一些优化以将字段压缩到标记中.例如:

use std::mem::size_of;

enum Node {
    N1_1 {
        is_good: bool,
        stuff: u32,
    },
    N1_2 {
        is_good: bool,
        left: Box<Node>,
        right: Box<Node>,
    },
}

enum Node2 {
    N2_1 { stuff: u32 },
    N2_2,
}

fn main() {
    println!("{:?} {:?}", size_of::<Node>(), size_of::<Node2>());
}
Run Code Online (Sandbox Code Playgroud)

这打印24 8.显然,正在发生的是字段被折叠到构造函数标记中.这种行为有保证吗?我不是在询问特定的内存表示是否保持不变,而是否承诺未来某个时间点的大小不会增加.

我想不出一个很好的理由,为什么他们可能想在某些时候改变代表性以增加尺寸,但也许这只是我缺乏想象力,所以我正在寻找一个"官方"答案.

与GitHub问题/ RFC的链接会很有帮助.我尝试浏览问题跟踪器,但无法找到任何内容.我能找到的最接近的东西bool是1字节大小,这是无法保证的.

rust

1
推荐指数
1
解决办法
137
查看次数