Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do "data Unit = Unit" and "()" behave differently in GHCi?

In GHCi: (> means output)

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

Why do Unit and () behave differently? There are also other types that behave like (), for example Int and Char. Are there any other such types?

Surprisingly, when I replace () by undefined, it behaves as I expected again:

let y = undefined :: ()
:p y
y = (_t2::())
like image 993
bennofs Avatar asked Feb 12 '14 16:02

bennofs


People also ask

What does GHCi mean in Haskell?

GHCi is GHC's interactive environment, in which Haskell expressions can be interactively evaluated and programs can be interpreted. Before reading this, read the GHCi section of the GHC User's Guide.

What does data do in Haskell?

data means that we're defining a new data type. The part before the = denotes the type, which is Bool. The parts after the = are value constructors. They specify the different values that this type can have.

Is GHCi an interpreter?

This library offers interfaces which mediate interactions between the ghci interactive shell and iserv , GHC's out-of-process interpreter backend.


1 Answers

You may want to look at this GHCi session:

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>

Basically, after x and x2 are defined, x is an unevaluated thunk. After I force the evaluation of x2, we discover that x was evaluated as well. Variable x3, despite being defined later, is never in an unevaluated state.

I believe that GHCi is playing some optimization here, creating just a single thunk for Unit. Every time you use the value constructor Unit, GHCi re-uses that thunk. Hence, the first time the single thunk is forced, every variable defined through the constructor appears in an evaluated state.

IIRC, small Integer literals use a shared pre-evaluated thunk as well:

Prelude> let y3 = 3 :: Integer
Prelude> :p y3
y3 = 3
Prelude> let y4 = 344444444444444 :: Integer
Prelude> :p y4
y4 = (_t3::Integer)
like image 168
chi Avatar answered Sep 30 '22 02:09

chi