Skip to content

can't hashComponents if bindings have free variables #6247

@lJoublanc

Description

@lJoublanc

Describe and demonstrate the bug

The problem manifests in the latest version of this library:

scratch/main> lib.install @ljoublanc/ad/@ljoublanc/broken

If you then edit examples.rollercoaster and add a watch expression that calls the blas library:


{{
Adapted from Fast AI course, chapter 4
}}
examples.rollercoaster :
  '{Exception,
  Random,
  Scope s,
  Adjoint Float matrix,
  LinearAlgebra Float (Dual matrix),
  Dense (Scope s) Float (Dual matrix)} [Float]
examples.rollercoaster =
  do
    use Debug trace
    use Float - > ^ fromNat
    use math %
    n = 20
    ones : Dual matrix m _1 Float
    ones = vector (List.of 1.0 n)
    time : Dual matrix m _1 Float
    time = vector <| (Nat.range 0 n |> List.map fromNat)
    speed =
      time
        |> toFloatList
        |> (>>)
             List.map
             List.map
             (t ->
               Random.float() Float.* 3.0
                 Float.+ 0.75 Float.* (t - 9.5) ^ 2.0
                 Float.+ 1.0)
        |> matrix
    trace "speed (solution)" (toFloatList speed)
    f :
      Dual matrix m _1 Float
      -> Dual matrix _3 _1 Float
      -> Dual matrix m _1 Float
    f t =
      note
        {{
        Originally this was `a * t ^ 2 + b * t + c`, but we've adjusted this
        because AD only works with tensors, not with scalars at the moment. We
        create a design matrix Φ, which contains `[t^2, t, 1]` as columns, and
        then the equation becomes just `Φ * w, w = [a,b,c]`.
        }}
      Φ : Dual matrix m _3 Float
      Φ =
        use List map
        use Nat *
        use mutable.ByteArray.Raw copyTo!
        tsquared : Dual matrix m _1 Float
        tsquared = t |> toFloatList |> (>>) map map (x -> x ^ 2.0) |> matrix
        match toPinned t with
          (GE (GeneralDense ColMajor m _ _), ts) ->
            buff = Scope.Raw.pinnedByteArray (m * 3 * 8)
            copyTo!
              (toRaw buff) 0 (tsquared |> toPinned |> at2 |> toRaw) 0 (m * 8)
            copyTo! (toRaw buff) (m * 8) (toRaw ts) 0 (m * 8)
            copyTo!
              (toRaw buff)
              (m * 2 * 8)
              (ones |> toPinned |> at2 |> toRaw)
              0
              (m * 8)
            fromPinned Type.float (GE (GeneralDense RowMajor m 3 3)) buff
          _ -> bug()
      params -> Φ math.* params
    mse :
      Dual matrix m _1 Float
      -> Dual matrix m _1 Float
      -> Dual matrix _1 _1 Float
    mse preds targets =
      use Float /
      use math * +
      ε = preds + -1.0 % targets
      1.0 / fromNat n % ε ^^ ᵀ * ε
    params : Dual matrix _3 _1 Float
    params = vector (List.replicate 3 Random.float)
    trace "starting parameters" <| toFloatList params
    Stream.toList << Stream.take 30 << Stream.map at2
      <| (Stream.unfold params cases
        w ->
          use math +
          lr = 1.0e-5
          preds = f time w
          loss = mse preds speed
          if toScalar loss > 0.1 then
            w' = w + Float.negate lr % Adjoint.adjoint w loss
            Some ((preds |> toFloatList, toScalar loss), w')
          else None)

> catch do 
    Scope.run do
      native.dense.run do
        vector [1.0] |> toFloatList

The transcript works fine, but doing this manually doesn't! I see the following error on loading my scratch.u, with the above contents:

Encountered exception:
can't hashComponents if bindings have free variables:
  ["User \"preds\""]
  ["User \"examples.rollercoaster\"","User \"examples.rollercoaster.doc\"","UnnamedWatch \"test\" \"ngadvgle4a\""]
CallStack (from HasCallStack):
  error, called at src/Unison/Hashing/V2/ABT.hs:130:11 in unison-hashing-v2-0.0.0-LVdCzBrxj3mLdSBxnVbuh3:Unison.Hashing.V2.ABT
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at src/Ki/Internal/Scope.hs:198:25 in ki-1.0.1.2-G0k6FwDdV3TDP6J4dPCKAy:Ki.Internal.Scope

Strangely, if I remove the definition of examples.rollercoaster from the scratch file, and just leave the watch expression, it works fine.

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • unison version: release/1.3.0 (built on 2026-05-13
  • OS/Architecture: Ubuntu

Additional context
Note the preds in the error message is a term in rollercoaster.
Also note, I've written a number of tests and examples within the dependend library blas and not run into this. Said library uses murmurHash - I don't know if that's related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions