I don't know what you are trying to do, but I do know why your program is rejected.
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 = Bar (STArray s Int Int) > > 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:[EMAIL PROTECTED]] | Sent: 06 August 2002 19:20 | To: Haskell Mailing List | Subject: ugliness with state parameter in ST stuff | | | 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 | [EMAIL PROTECTED] | than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume | | _______________________________________________ | Haskell mailing list | [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell | _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell