Skip to content

Commit

Permalink
#39 Fix fromListWithDef divergence
Browse files Browse the repository at this point in the history
fromListWithDef diverges when passed an infinite list, for the following
reasons:

Reason 1:

  * fromListWithDef calls Data.Primitive.Array.fromListN (bits + 1).
    fromListN requires that the length of the list that is passed to it
    is exactly bits + 1. To ensure this, it forces the spine of the list
    that is passed to it.

  * The list that is passed to fromListN is generated by go0, which
    calls go. When xs is infinite, go k xs will be infinite. Therefore,
    fromListN will throw an error since go0 yields a list longer than
    bits + 1.

Even if we take the first bits + 1 elements of go0 before passing to
fromListN, there is another problem.

Reason 2:

  * As fromListN forces the spine, it will compute go 0 xs0, go 1 xs1,
    ..., go 63 xs63, for some xs0, xs1, ..., xs63.

  * This in turn requires computing measureOff (2^0) xs0,
    measureOff (2^1) x1, ..., measureOff (2^63) x63, which is
    essentially divergent.

To avoid these problems, we

  * Add a check in go to break recursion and ensure that the list that
    is passed to fromListN has length (bits + 1).

  * Rearrange how we compute go, so that measureOff is not forced while
    forcing the spine of go.

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# Date:      Thu Apr 11 18:55:38 2024 -0700
#
# On branch fix-fromListWithDef
# Your branch is up to date with 'origin/fix-fromListWithDef'.
#
# Changes to be committed:
#	modified:   src/Data/Chimera/Internal.hs
#
# Untracked files:
#	.stack-work/
#	stack.yaml.lock
#
  • Loading branch information
pgujjula committed Apr 12, 2024
1 parent ecacbd1 commit 562b312
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/Data/Chimera/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -553,13 +553,19 @@ fromListWithDef a = Chimera . fromListN (bits + 1) . go0
[] -> G.singleton a : map (\k -> G.replicate (1 `shiftL` k) a) [0 .. bits - 1]
x : xs -> G.singleton x : go 0 xs

go k xs = case measureOff kk xs of
Left l ->
G.fromListN kk (xs ++ replicate l a)
: map (\n -> G.replicate (1 `shiftL` n) a) [k + 1 .. bits - 1]
Right (ys, zs) -> G.fromListN kk ys : go (k + 1) zs
go k xs =
if k == bits
then []
else v : go (k + 1) zs
where
kk = 1 `shiftL` k
(v, zs) =
case measureOff kk xs of
Left l ->
if l == kk
then (G.replicate kk a, [])
else (G.fromListN kk (xs ++ replicate l a), [])
Right (ys, zs') -> (G.fromListN kk ys, zs')

-- | Create a stream of values from a given infinite list.
--
Expand Down

0 comments on commit 562b312

Please sign in to comment.