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