My newbie's attempt to express the behavior of operator ||
from C/C++ in Haskell:
orElse :: Bool -> (a -> Bool) -> (a -> Bool)
orElse True _ = const True
orElse False pred = pred
Can this be generalized so that it can accept a -> b -> Bool
, a -> b -> c -> Bool
and so on as its 2nd argument?
Looked at overloading techniques, HKTs et. al. - nothing seems to deal with generalization by kind...
Edit: I now understand why this was a bad example (reading the definition of operator||
in prelude helped) but am still wondering at the larger question as posed.
You can probably craft your wanted function using type classes, but I'm not sure this is a great idea.
class MagicOr a where
magicOr :: a -> a -> a
instance MagicOr Bool where
magicOr = (||)
instance MagicOr b => MagicOr (a -> b) where
magicOr f g = \x -> f x `magicOr` g x
-- or, alternatively,
-- magicOr = liftA2 magicOr
The code above defines a magicOr
function that can be used on two arguments of type Bool
, or of type a -> Bool
, or of type a -> b -> Bool
, and so on.
So far, I guess this code is not too bad, and fairly usable.
Still, depending on what you actually need to do, you might end up building a complex type class machinery, which might be somewhat fragile to use. An example is printf
. Its definition is rather tricky since it has to handle an unknown number of parameters. Further, if used wrong, it can confuse the type checker which will spew error messages which are hard to understand.
Feel free to experiment, of course, and see by yourself. Just be warned that type classes, when abused too much, sometimes lead to unwieldy code.