Q:

Detect bottom value in Haskell

I've written a haskell function which splits a list xs into (init xs, last xs) like so:
split xs = split' [] xs
    where
        split' acc (x:[]) = (reverse acc, x)
        split' acc (x:xs) = split' (x:acc) xs

Since an empty list can not be split in this way, there is no match for the empty list. However, I did not want to simply error ... the function. Thus I defined the following:
split [] = ([], undefined)

Thanks to lazy evaluation I can thus define a safe init which simply returns the empty list for the empty list:
init' = fst . split

Is there some way how I could detect the undefined if I tried to access it, such that
last' xs
  | isUndefined (snd xs) = ...
  | otherwise            = ...

I do know about Maybe and Either, and that those are a better choice for expressing what I want. However I wondered if there is a way to detect an actual value of undefined, i.e. in terms of catching errors, like catching exceptions.

A:

undefined is no better than using error. In fact, undefined in Prelude is defined as
undefined =  error "Prelude.undefined"

Now, a function that can't result in an error is called a "total function", i.e. it is valid for all input values.
The split function you've currently implemented has the signature
split :: [a] -> ([a], a)

This is a problem, since the type signature promises that the result always contains a list and an element, which is clearly impossible to provide for empty lists of generic type.
The canonical way in Haskell to address this is to change the type signature to signify that sometimes we don't have a valid value for the second item.
split :: [a] -> ([a], Maybe a)

Now you can write a proper implementation for the case where you get an empty list
split [] = ([], Nothing)
split xs = split' [] xs
    where
        split' acc (x:[]) = (reverse acc, Just x)
        split' acc (x:xs) = split' (x:acc) xs

Now you can detect the missing value case by pattern-matching
let (init', last') = split xs
in case last' of
    Nothing -> ... -- do something if we don't have a value
    Just x  -> ... -- do something with value x

A:

Because bottom subsumes non-termination, the function isUndefined would have to solve the halting problem and thus cannot exist.
But note that even if it existed, you still could not tell if the undefined value in the 2nd element of your tuple was put there through your split function or if the last element of the list was already undefined.

A:

The error function doesn't do anything until it is evaluated, so you can do something like:
split [] = ([], error "split: empty list")

last' = snd . split

