# Can I write a duplicate function which doesn't share?

**URL:** <https://discourse.haskell.org/t/can-i-write-a-duplicate-function-which-doesnt-share/7854>\
**Category:** Uncategorized\
**Created:** [October 11, 2023, 5:32pm UTC](https://discourse.haskell.org/t/can-i-write-a-duplicate-function-which-doesnt-share/7854 "2023-10-11T17:32:05Z")\
**Posts on this page:** 1\
**Showing post:** 9

<div class="post-metadata">

**Author:** ![sgraf](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sgraf/32/392_2.png) [@sgraf](https://discourse.haskell.org/u/sgraf)\
**Post date:** [October 12, 2023, 7:45am UTC](https://discourse.haskell.org/t/can-i-write-a-duplicate-function-which-doesnt-share/7854/9 "2023-10-12T07:45:04Z")

</div>

I think `oneShot` is a bit different to `noupdate`, because it needs to be applied to a function whose body GHC will no longer be prone to float stuff out of (still, it well _could_). E.g.,

```haskell
oneShot $ \() -> [1..100]

```

Without `oneShot`, GHC will just float out the list. With `oneShot`, it won’t, because there is no benefit to: The user said that the lambda will only be entered at most once. If you had written

```haskell
f y = 
  let x = fib y in
  let g = oneShot $ \n -> [1..n+x] in
  g 0 ++ g 1 ++ g 2

```

Then GHC would also be allowed to float `fib y` _inside_ the lambda, thus accidentally duplicating _more_ work than the programmer intended to.

If we instead had

```haskell
f x = g x
  where
     g 0 = oneShot $ \() -> [1..x]
     g n = g (n-1) () ++ g (n-2) ()

```

Then _I think_ that GHC will float the list out of `g` where it is evaluated at most once per invokation of `f`.  
So `oneShot` is neither more general nor more specific than `noupdate`.

It is notoriously hard to identify and maintain all the places where GHC might float stuff out in this manner (after all it’s one of the tenets of laziness to float freely), which is perhaps the reason there is no `noupdate` to this day. Not sure what became of Joachim’s work.

The way I’d work around this is by defining

```haskell
noupdate :: ((forall a. a -> a) -> r) -> r
noupdate f = f id
{-# OPAQUE noupdate #-}

foo n = do
  let xs = noupdate (\hide -> [1..hide n])
  print (xs !! 1000000)
  expensive
  print (xs !! 1000001)

```

This in itself only introduces a float barrier for the expression `[1..n]` wherever `hide` is used, so the user eplicitly declares which parts of a computation should not be shared, rather than a wildcard "duplicate `xs`", which might transitively duplicate the whole heap.

Then in CorePrep you’d see something like

```haskell
let f = {...} \r [hide] enumFromTo ... hide ...
let x = {f} \u noupdate f in
...

```

Syntax: `{f}` lists `f` as the free variable of `x`'s closure, `\r` means “reentrant” (think: function), `\u` means “updateable” (think: thunk), `[hide]` is a singleton list of lambdas.

To get the desired effect, we need GHC to detect `\u noupdate f` and turn it into `\s f id`, where `\s` means “single-entry thunk” (which is essentially the same as a function, `\r`, only that we may detect `<<loop>>`s if we wanted to. Perhaps `\r` is a better fit because we sometimes validate `\s` by counting the number of actual entries, which will be more than once for serious use of `noupdate`).

Should not be too hard to implement! Just needs someone dedicated to baby-sit the GHC proposal.

---

_[View the full topic](https://discourse.haskell.org/t/can-i-write-a-duplicate-function-which-doesnt-share/7854)._
