【问题标题】:Why do "data Unit = Unit" and "()" behave differently in GHCi?为什么“data Unit = Unit”和“()”在 GHCi 中的行为不同?
【发布时间】:2014-02-12 16:55:22
【问题描述】:

在 GHCi 中:(> 表示输出)

data Unit = Unit
let x = Unit
let y = ()
:p x
> x = (_t1::Unit)
:p y
> y = ()
:i ()
> data () = ()    -- Defined in `GHC.Tuple'

为什么Unit() 的行为不同?还有其他类型的行为类似于(),例如IntChar。还有其他这种类型吗?

令人惊讶的是,当我将 () 替换为 undefined 时,它的行为再次符合我的预期:

let y = undefined :: ()
:p y
y = (_t2::())

【问题讨论】:

  • 我也不完全理解这个区别,但它似乎与正在编译的代码有关。例如let x = True:p x 也显示x = True。并且使用Unit 定义编译模块使其与() 的行为相匹配。
  • 我有个主意。 Unit 构造函数就像一个顶级常量。如果它被评估一次,它将在程序的整个运行时间内保持评估。我猜有些值默认是evaluated(因为几乎每个程序都需要它们)。您可以在尝试let x = Unit; y = Unit 时对此进行测试。即使你只评估y,之后也会评估x。
  • @bennofs 如果您将类型设为newtype Unit = Unit ()data Unit = Unit (),您也会得到不同的行为,它们的行为更像()

标签: haskell lazy-evaluation evaluation


【解决方案1】:

您可能想查看此 GHCi 会话:

Prelude> data Unit = Unit deriving Show
Prelude> let x = Unit
Prelude> let x2 = Unit
Prelude> :p x
x = (_t1::Unit)
Prelude> x2
Unit
Prelude> :p x
x = <.:Interactive.Unit>
Prelude> let x3 = Unit
Prelude> :p x3
x3 = <.:Interactive.Unit>

基本上,在定义 xx2 之后,x 是一个未评估的 thunk。在我强制评估x2 之后,我们发现x 也被评估了。变量x3 尽管在后面定义,但永远不会处于未评估状态。

我相信 GHCi 在这里进行了一些优化,只为 Unit 创建了一个 thunk。每次使用值构造函数Unit 时,GHCi 都会重新使用该 thunk。因此,第一次强制执行单个 thunk 时,通过构造函数定义的每个变量都会出现在评估状态。

IIRC,小的 Integer 文字也使用共享的预评估 thunk:

Prelude> let y3 = 3 :: Integer
Prelude> :p y3
y3 = 3
Prelude> let y4 = 344444444444444 :: Integer
Prelude> :p y4
y4 = (_t3::Integer)

【讨论】:

    猜你喜欢
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多