
Felipe,
Regardless, there's a trick that you may use whenever you want to know the types of something. Just make a function where everything you don't know is an argument, and ask GHCi to give you its type.
That's a great trick. Thanks everybody for your help. Patrick
Supposing it's Haskell 98, GHCi will always give you the most general type. With this example:
Prelude> :t \ds applyOp op x y -> applyOp op x y >>= flip (:) ds \ds applyOp op x y -> applyOp op x y >>= flip (:) ds :: [a] -> (t -> t1 -> t2 -> [a]) -> t -> t1 -> t2 -> [a]
So we see that
ds :: [a] applyOp :: t -> u -> v -> [a] op :: t x :: u y :: v applyOp op x y >>= flip (:) ds :: [a]
works. In other words, it's an expression in the list monad. Whether it is useful or not, I don't know =). Adding the 'return':
Prelude> :t \ds applyOp op x y -> applyOp op x y >>= return . flip (:) ds \ds applyOp op x y -> applyOp op x y >>= return . flip (:) ds :: (Monad m) => [a] -> (t -> t1 -> t2 -> m a) -> t -> t1 -> t2 -> m [a]
So now we get:
Monad m => ds :: [a] applyOp :: t -> u -> v -> m a op :: t x :: u y :: v applyOp op x y >>= return . flip (:) ds :: m [a]
Seems much more useful! So 'applyOp op x y :: m a' and the result of everything is 'm [a]'.
Note that if there is a type mismatch (even with the general arguments!), GHCi will tell you right away. For example,
Prelude> :t \ds applyOp op x y -> applyOp op x y >>= fmap . flip (:) ds
<interactive>:1:48: Couldn't match expected type `a -> b' against inferred type `[a1]' In the second argument of `(.)', namely `flip (:) ds' In the second argument of `(>>=)', namely `fmap . flip (:) ds' In the expression: applyOp op x y >>= fmap . flip (:) ds
This means that no matter what ds, applyOp, op, x and y you choose, 'applyOp op x y >>= fmap . flip (:) ds' will always be ill-typed.
Cheers,
-- Felipe.
-- ===================== Patrick LeBoutillier Rosemère, Québec, Canada