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 | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
On Tuesday 06 August 2002 11:19 am, Hal Daume III wrote:
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
I think that you really meant "instance Foo (forall s . Bar s)", but unfortunately ghc doesn't allow that kind of polymorphism in instance declarations. Instead, your instance as written has the free type variable 's' in it, which tells ghc that the following definitions should work for all possible values of 's'. But instances for (Bar Int) or (Bar Bool), etc. certainly would not work. Try this instead:
instance Foo (Bar RealWorld) where foo = stToIO . getFirst
It should work OK, since it doesn't have the free type variable. - Brian Huffman
Try this instead:
instance Foo (Bar RealWorld) where foo = stToIO . getFirst
It should work OK, since it doesn't have the free type variable.
Yes, this is what I have. But this kind of makes the fact that I'm in ST useless, since afaik (ST RealWorld) is basically the same as IO, so there's no reason for me to stay in the ST realm... - Hal
Hal Daume III writes: | > Try this instead: | > | > > instance Foo (Bar RealWorld) where | > > foo = stToIO . getFirst | > | > It should work OK, since it doesn't have the free type variable. | | Yes, this is what I have. But this kind of makes the fact that I'm | in ST useless, since afaik (ST RealWorld) is basically the same as | IO, so there's no reason for me to stay in the ST realm... How about making Foo a class of constructors of kind *->* instead of *? import ST data Bar s = Bar (STArray s Int Int) getFirst (Bar arr) = readSTArray arr 0 class Foo a where foo :: a s -> IO Int instance Foo Bar where foo = stToIO . getFirst
participants (3)
-
Brian Huffman -
Hal Daume III -
Tom Pledger