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