I think if you want to imitate this, the simplest way is akin to an answer posted in the comments:
f _ = undefined
However, this is lazy:
f (error "aw beans") -- undefined
While the empty case is strict:
(\ case {} :: X1 :~: X2 -> Void) (error "aw beans") -- beans
So a better replacement would use seq:
impossible :: a -> Void
impossible x = x `seq` impossible x
Or BangPatterns:
{-# Language BangPatterns #-}
impossible :: a -> Void
impossible !x = impossible x
Whereupon you can just write f = impossible, which seems pretty good to me. (The quantifier on a is logically more like “for any” than “for all”, but oh well.) You could of course throw something slightly more descriptive instead of going into an infinite loop in case the situation isn’t actually impossible—error "the impossible was possible after all".
This should also work with the old-fashioned definition of Void as data Void = Void !Void or newtype Void = Void Void in the void package.
f _ = undefinedwork?undefinedto use an empty case. So I'd like to know how I can write it withoutundefined.Data.Void.absurdis also defined usingcase x of {}.)casenormally has one or more branches; generalizing to zero branches (because no pattern could match) still leaves thecase ... ofheader, so there's something to write to indicate that's what you want to do. But function definition syntax has you write an equation for each branch, so zero branches should mean zero equations, leaving nothing at all! But that can't be told apart from just not having implemented the function yet.