ugliness with state parameter in ST stuff

Hal Daume III hdaume@ISI.EDU
Tue, 6 Aug 2002 11:19:37 -0700 (PDT)


Sorry for the flood of emails this morning, but I've got something which
has really got me scratching my head.

Suppose I have a class:

> class Foo a where
>     foo :: a -> IO Int

and a datatype with a single function:

> data Bar s = Bar (STArray s Int Int)
> 
> getFirst :: Bar s -> ST s Int
> getFirst (Bar arr) = readArray arr 0

Now, I want to make (Bar s) and instance of Foo.  But I can't seem to do
this.  If I use:

> instance Foo (Bar s) where
>     foo = stToIO . getFirst

GHC complains:

    Cannot unify the type-signature variable `s'
	with the type `RealWorld'
	Expected type: Bar s -> IO Int
	Inferred type: Bar RealWorld -> IO Int
    In the expression: stToIO . getFirst
    In the definition of `foo': stToIO . getFirst

and if I use:

> instance Foo (Bar s) where
>     foo = return . runST . getFirst

GHC complains:

    Inferred type is less polymorphic than expected
	Quantified type variable `s' escapes
	Expected type: ST s a -> c
	Inferred type: (forall s1. ST s1 a) -> a
    In the first argument of `(.)', namely `runST'
    In the second argument of `(.)', namely `runST . getFirst'

Is there no way to do this?  I can change the definition of Foo to:

> class Foo2 a where
>     foo2 :: (forall s . a s) -> IO Int

I can define:

> instance Foo2 Bar where
>     foo2 = stToIO . getFirst

Which I suppose works, but the problem is that in real life, "Foo" is
"Binary" and I can't really change it.

Suggestions?  (Other than simply moving all my ST stuff over to the IO
monad?)

 - Hal

--
Hal Daume III

 "Computer science is no more about computers    | hdaume@isi.edu
  than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume