Unit unboxed tuples
Dan Doel
dan.doel at gmail.com
Wed Jan 11 20:28:37 CET 2012
On Wed, Jan 11, 2012 at 8:41 AM, Simon Marlow <marlowsd at gmail.com> wrote:
> On 10/01/2012 16:18, Dan Doel wrote:
>>
>> Copying the list, sorry. I have a lot of trouble replying correctly
>> with gmail's interface for some reason. :)
>>
>> On Tue, Jan 10, 2012 at 11:14 AM, Dan Doel<dan.doel at gmail.com> wrote:
>>>
>>> On Tue, Jan 10, 2012 at 5:01 AM, Simon Marlow<marlowsd at gmail.com> wrote:
>>>>
>>>> On 09/01/2012 04:46, wren ng thornton wrote:
>>>>>
>>>>> Shouldn't (# T #) be identical to T?
>>>>
>>>>
>>>> No, because (# T #) is unlifted, whereas T is lifted. In operational
>>>> terms,
>>>> a function that returns (# T #) does not evaluate the T before returning
>>>> it,
>>>> but a function returning T does. This is used in GHC for example to
>>>> fetch a
>>>> value from an array without evaluating it, for example:
>>>>
>>>> indexArray :: Array# e -> Int# -> (# e #)
>>
>>
>> I don't really understand this explanation. (# T #) being unlifted
>> would mean it's isomorphic to T under the correspondence e<-> (# e
>> #). _|_ = (# _|_ #) : (# T #), so this works.
>>
>> Does the difference have to do with unboxed types? For instance:
>>
>> foo :: () -> Int#
>> foo _ = foo ()
>> bar :: () -> (# Int# #)
>> bar _ = (# foo () #)
>>
>> baz = case bar () of _ -> 5 -- 5
>> quux = case foo () of _ -> 5 -- non-termination
>>
>> Because in that case, either (# Int# #) is lifted, or the Int# is
>> effectively lifted when inside the unboxed tuple. The latter is a bit
>> of an oddity.
>
>
> Unboxed types cannot be lifted, so in fact bar compiles to this:
>
> bar = \_ -> case foo () of x -> (# x #)
>
> and both baz and quux diverge.
>
> It might help to understand (# T #) by translating it to (# T, () #).
> There's really no difference.
Then I'm afraid I still don't understand the difference. Is it that
case in core always evaluates? So:
case undefined of x -> ...
blows up, while
case (# undefined #) of (# x #) -> ...
does not?
Also, if so, how is (core-wise):
foo :: ... -> (# T #)
case foo <v> of (# x #) -> ...
different from:
foo :: ... -> T
let x = foo <v> in ...
Stack vs. heap allocation?
Sorry for being rather thick.
-- Dan
More information about the Glasgow-haskell-users
mailing list