
Hi every one ! A long time ago, I got a problem about Map.lookup and lazyness (the programmer's one). Since it's still bugging me, I'd like to ask for some external advice. Let's say I've build a big documentation index (:: Map Key URL) where both Key and URL are Strings. The problem is that my keys have some random prefixes (ie the key "foo" could be store either as "foo", "a_foo", "b_foo", "g_foo", "gtk_foo" or "pango_foo"). How could I implement effectively in Haskell a function which return me the first (and only the first!) correct URL ? For now, I'm doing something like this: {{{ type Key = String type URL = String lookupDocumentation :: Map Key URL -> Key -> Maybe URL lookupDocumentation myMap key = let r = map (lookupSymbols myMap) [ key , "a_" ++ key , "b_" ++ key , "g_" ++ key , "gtk_" ++ key , "pango_" ++ key ] in case catMaybes r of [] -> Nothing (x:_) -> Just x }}} My problem is: will `lookupDocumentation` perform n=6 lookups in my Map, or will Haskell-built-in-lazyness only evaluate till an URL is found ? regards, /John

On Thu, Dec 2, 2010 at 1:04 PM, John Obbele
{{{ type Key = String type URL = String
lookupDocumentation :: Map Key URL -> Key -> Maybe URL lookupDocumentation myMap key = let r = map (lookupSymbols myMap) [ key , "a_" ++ key , "b_" ++ key , "g_" ++ key , "gtk_" ++ key , "pango_" ++ key ] in case catMaybes r of [] -> Nothing (x:_) -> Just x }}}
My problem is: will `lookupDocumentation` perform n=6 lookups in my Map, or will Haskell-built-in-lazyness only evaluate till an URL is found ?
You can test this by creating a Map that contains undefined values e.g. {{{ lookupDocumentation (insert "b_somekey" undefined (singleton "a_somekey" "somevalue")) "somekey" }}} Since "a_somekey" is checked before "b_somekey" and "a_somekey" is in the map, this should work if the function is lazy enough. Johan

On Thursday 02 December 2010 13:15:02, Johan Tibell wrote:
On Thu, Dec 2, 2010 at 1:04 PM, John Obbele
wrote: {{{ type Key = String type URL = String
lookupDocumentation :: Map Key URL -> Key -> Maybe URL lookupDocumentation myMap key =
let r = map (lookupSymbols myMap) [ key , "a_" ++ key , "b_" ++ key , "g_" ++ key , "gtk_" ++ key , "pango_" ++ key ] in case catMaybes r of [] -> Nothing (x:_) -> Just x
With an import from Control.Monad, you can write that as msum (map (lookupSymbols myMap) [pre ++ key | pre <- ["", "a_", "b_", "g_", "gtk_", "pango_"]]
}}}
My problem is: will `lookupDocumentation` perform n=6 lookups in my Map, or will Haskell-built-in-lazyness only evaluate till an URL is found ?
It will only perform the lookups needed to determine the outcome. If the un-prefixed key is in the map, only one lookup will be done.
You can test this by creating a Map that contains undefined values e.g.
{{{ lookupDocumentation (insert "b_somekey" undefined (singleton "a_somekey" "somevalue")) "somekey" }}}
Since "a_somekey" is checked before "b_somekey" and "a_somekey" is in the map, this should work if the function is lazy enough.
That would work even if all prefixes are looked up, catMaybes [Nothing, Just "somevalue", Just undefined, Nothing, Nothing, Nothing] evaluates to ["somevalue",undefined] without a problem. To check it, you need a key which throws an error if compared to one of the later prefixed keys, for example lookupDocumentation (insert ("b_somekey" ++ undefined) "b" (singleton "a_somekey" "a")) "somekey" works while inserting something with the key ("somekey" ++ undefined) throws an exception.
Johan

Hi Johan & Daniel, thanks for you answers. I had forgotten the MonadPlus/msum and the trick to use undefined. ... althought the trick with undefined here takes me quiet some time to grasp it ... but now I know my function works lazily. regards, /John
participants (3)
-
Daniel Fischer
-
Johan Tibell
-
John Obbele