This might seem artificial, but I can't seem to find an obvious answer to the following:
Say I have the following imports:
import qualified Data.Map as M
import qualified Data.HashMap.Lazy as HML
Now I have some function (comp
) that takes some list, does something, creates a map, returns it.
My question is how do I have two ways of calling comp
so that its calls (say) to insert
and size
map correctly?
As a strawman, I could write two copies of this function, one referencing M.insert
and M.size
, while the other references HML.insert
and HML.size
... but how do I "pass the module as a parameter", or indicate this otherwise?
Thanks!
Edit: to make this less abstract these are the exact definitions of comp
:
mapComp :: KVPairs -> IO ()
mapComp kvpairs = do
let init = M.empty
let m = foldr ins init kvpairs where
ins (k, v) t = M.insert k v t
if M.size m /= length kvpairs
then putStrLn $ "FAIL: " ++ show (M.size m) ++ ", " ++ show (length kvpairs)
else pure ()
hashmapComp :: KVPairs -> IO()
hashmapComp kvpairs = do
let init = HML.empty
let m = foldr ins init kvpairs where
ins (k, v) t = HML.insert k v t
if HML.size m /= length kvpairs
then putStrLn $ "Fail: " ++ show (HML.size m) ++ ", " ++ show (length kvpairs)
else pure ()
Edit (2): this turned out to be way more interesting than I anticipated, thanks to everyone who responded!
Bool
or some specially-constructed custom data type) to indicate which module you want to use. Perhaps others will know some more sophisticated way to do it. – Cristobalcristobalitelet insertfn = if <param> then M.insert else HML.insert
(and similarly forsizefn
) and then useinsertfn
as needed? I guess that works, but then I'm wondering whether there's an idiomatic way to do this when I have more than two possible modules. – Monopode