ugliness with state parameter in ST stuff

Simon Peyton-Jones simonpj@microsoft.com
Wed, 28 Aug 2002 12:20:33 +0100


I don't know what you are trying to do, but I do know why your program
is rejected.=20

The *whole point* of a value of type (STArray s Int Int) is that it can
only
be read by a state thread with the same type parameter 's' as the array.
Given your decls

> class Foo a where
>     foo :: a -> IO Int
>
> data Bar s =3D Bar (STArray s Int Int)
>=20
> instance Foo (Bar s) where ...

it is absolutely right that you are going to fail.   To implement the
instance decl, you need to make

	foo :: forall s. Bar s -> IO Int

But you can read an STArray parameterised by an *arbitrary* state type s
using the IO monad!  Of course not!  There is even a theorem in 'State
in Haskell'
that makes just this point: separate state threads really are separate,
and
you can't read a reference from one in another.

No, no, no!

Simon

| -----Original Message-----
| From: Hal Daume III [mailto:hdaume@ISI.EDU]=20
| Sent: 06 August 2002 19:20
| To: Haskell Mailing List
| Subject: ugliness with state parameter in ST stuff
|=20
|=20
| Sorry for the flood of emails this morning, but I've got=20
| something which has really got me scratching my head.
|=20
| Suppose I have a class:
|=20
| > class Foo a where
| >     foo :: a -> IO Int
|=20
| and a datatype with a single function:
|=20
| > data Bar s =3D Bar (STArray s Int Int)
| >=20
| > getFirst :: Bar s -> ST s Int
| > getFirst (Bar arr) =3D readArray arr 0
|=20
| Now, I want to make (Bar s) and instance of Foo.  But I can't=20
| seem to do this.  If I use:
|=20
| > instance Foo (Bar s) where
| >     foo =3D stToIO . getFirst
|=20
| GHC complains:
|=20
|     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
|=20
| and if I use:
|=20
| > instance Foo (Bar s) where
| >     foo =3D return . runST . getFirst
|=20
| GHC complains:
|=20
|     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'
|=20
| Is there no way to do this?  I can change the definition of Foo to:
|=20
| > class Foo2 a where
| >     foo2 :: (forall s . a s) -> IO Int
|=20
| I can define:
|=20
| > instance Foo2 Bar where
| >     foo2 =3D stToIO . getFirst
|=20
| Which I suppose works, but the problem is that in real life,=20
| "Foo" is "Binary" and I can't really change it.
|=20
| Suggestions?  (Other than simply moving all my ST stuff over to the IO
| monad?)
|=20
|  - Hal
|=20
| --
| Hal Daume III
|=20
|  "Computer science is no more about computers    | hdaume@isi.edu
|   than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
|=20
| _______________________________________________
| Haskell mailing list
| Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
|=20