Hi Yotam,
A type variable `a` means that you know absolutely nothing about the variable, and can't treat it specially. So you can't special-case your function to "either Foo or Bar."
You can achieve your goal like this:
func :: Either Foo Bar -> (Int -> Int)
func (Left (Foo a _)) = a
func (Right (Bar a)) = a
The kind of runtime type inspection you might be used to from other langauges is available via the Typeable class. It's extremely non-idiomatic Haskell, and I strongly recommend against writing this sort of code. For completeness, this also works:
func :: Typeable a => a -> Maybe (Int -> Int)
func a = maybeFoo <|> maybeBar
where
maybeFoo = case cast a of
Just (Foo a _) -> Just a
Nothing -> Nothing
maybeBar = case cast a of
Just (Bar a) -> Just a
Nothing -> Nothing