[Haskell] more newbie questions regarding do syntax, mondic context & Data.HashTable

Robert Dockins robdockins at fastmail.fm
Thu Dec 29 09:36:57 EST 2005


On Dec 29, 2005, at 9:06 AM, Hunter Kelly wrote:

> Hi there, I'm having some trouble trying to get information out
> of a HashTable.
>
> I'm using it to represent a set (I'm using a hash table for O(1)
> speed reasons to compare against Data.Sets O(lgN) operations).
>
> I'm trying to write a simple function, member, which returns whether
> or not a key is in the HashTable.
>
> I've tried the following:
>
> member :: HashTable String Int -> String -> Bool
> member hash x = let r = do return (Data.HashTable.lookup hash x )
>                           in case r of
>                                Nothing -> False
>                                (Just v) -> True
>
> But this seems to always return True.  I _think_ the type of r here is
> IO (Maybe Int), but I'm trying to unwrap the IO part.

This is due to the fact that "Maybe" is a monad; r actually has the  
type "Maybe (IO (Maybe Int))".  Calling "return" in the Maybe monad  
will always generate a value of the form "Just x".  Then you pattern  
match on that and, surprise, it matches "Just v"

> However, if I try:
>
> member :: HashTable String Int -> String -> Bool
> member hash x = let r = do Data.HashTable.lookup hash x
>                            in case r of
>                                Nothing -> False
>                                (Just v) -> True
>
> I get the following error:
>
>
> figt.hs:46:31:
>     Couldn't match `IO (Maybe Int)' against `Maybe a'
>       Expected type: IO (Maybe Int)
>       Inferred type: Maybe a
>     When checking the pattern: Nothing
>     In a case alternative: Nothing -> False
>
>
>
> How can I get at the underlying value?  Can I only access it from
> within a "do" construct?
> Is there anyway to get at this function to return just True or False?

Not really.  If it did, then it wouldn't really be a function (in the  
maths sense).

> Or has using something that uses an IO monad "polluted" everything
> else that depends on the answer?

Essentially, that is correct.  Once you go into the IO monad you  
can't get back out.  You can only use HashTable in IO level code.  If  
you need pure sets, use Data.Set and friends.

This is more or less how I would write the member operation on  
Data.HashTable.

member:: String -> HashTable String Int -> IO Bool
member x hash = do
       r <- lookup hash x
       return (isJust r)



See the following for more about the IO monad:


http://haskell.org/hawiki/ThatAnnoyingIoType
http://haskell.org/hawiki/UsingIo


Or check out the tutorials at:

http://www.haskell.org/learning.html



Rob Dockins

Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG



More information about the Haskell mailing list