0
votes

The Problem:

I can't find my way to understand the error in this code:

import Prelude
import Data.Array.ST (STArray, modify, run, thaw, freeze)

mpi :: forall a. Array a -> Array a
mpi array = run do
  mutableArray <- thaw array
  freeze mutableArray

The error:

Could not match type
         
    Array
         
  with type
              
    STArray h0
              

while trying to match type Array a2
  with type STArray h0 t1
while checking that expression (bind (thaw array)) (\mutableArray ->     
                                                      freeze mutableArray
                                                   )                     
  has type ST h0 (STArray h0 t1)
in value declaration mpi

where a2 is a rigid type variable
        bound at (line 0, column 0 - line 0, column 0)
      h0 is a rigid type variable
        bound at (line 9, column 17 - line 11, column 22)
      t1 is an unknown type

It says t1 is an unknown type, but I'm pretty sure it should be a2. I'm not sure how or where t1 is introduced. thaw should return type ST h (STArray h a) which gets bound to mutableArray :: STArray h a


If I specialize this function, it becomes clearer but no less confusing

mpi :: Array Int -> Array Int
mpi array = run do
  mutableArray <- thaw array
  freeze mutableArray

I get this error:

  Could not match type
         
    Array
         
  with type
              
    STArray h0
              

while trying to match type Array Int
  with type STArray h0 t1
while checking that expression (bind (thaw array)) (\mutableArray ->     
                                                      freeze mutableArray
                                                   )                     
  has type ST h0 (STArray h0 t1)
in value declaration mpi

where h0 is a rigid type variable
        bound at (line 9, column 17 - line 11, column 22)
      t1 is an unknown type

If I explicitly type the left-hand side,

mpi :: Array Int -> Array Int
mpi array = run do
  (mutableArray :: STArray _ Int) <- thaw array
  freeze mutableArray

or write it without do notation:

mpi :: Array Int -> Array Int
mpi array = run $ thaw array >>= freeze

The error doesn't really change. In each case, I have trouble understanding where t1 is introduced.

The Question:

  1. What's wrong with what I've written?
  2. What steps could I be taking with similar problems in the future to debug this on my own?
1

1 Answers

2
votes

You're using the wrong version of run.

The one you're using is from Data.Array.ST.
But the one your code assumes is from Control.Monad.ST.

The former takes an ST computation that returns an STArray, and then runs that computation, freezes the resulting array, and returns it as an immutable array.
The latter takes an ST computation that returns something, and then runs that computation and returns the resulting something.

Your do block is returning Array a, but then you're calling Data.Array.ST.run, which expects STArray h a, so the types don't match. This is exactly what the error message says: can't match Array a with STArray h a.

Fix option 1: import the other run:

import Prelude
import Control.Monad.ST (run)
import Data.Array.ST (STArray, modify, thaw, freeze)

mpi :: forall a. Array a -> Array a
mpi array = run do
  mutableArray <- thaw array
  freeze mutableArray

Fix option 2: return the STArray from your do block, don't freeze it:

import Prelude
import Data.Array.ST (STArray, modify, run, thaw, freeze)

mpi :: forall a. Array a -> Array a
mpi array = run do
  mutableArray <- thaw array
  pure mutableArray