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

Reply via email to