Define lower value in Haskell

I wrote a haskell function that splits the xs list into (init xs, last xs) as follows:

 split xs = split' [] xs where split' acc (x:[]) = (reverse acc, x) split' acc (x:xs) = split' (x:acc) xs 

Since an empty list cannot be split this way, there is no match for an empty list. However, I did not want just an error ... function. So I defined the following:

 split [] = ([], undefined) 

Thanks to lazy evaluation, I can thus define a safe init that simply returns an empty list for an empty list:

 init' = fst . split 

Is there a way to detect undefined if I tried to access it, so

 last' xs | isUndefined (snd xs) = ... | otherwise = ... 

I know about Maybe and Either , and that it is the best choice for expressing what I want. However, I wondered if there is a way to detect the actual value of undefined, i.e. in terms of trap errors such as catching exceptions.

+8
exception-handling haskell
source share
5 answers

Since the lower part does not require interruption, the isUndefined function should solve the problem of stopping and, therefore, cannot exist.

But note that even if it existed, you still could not determine whether the value was undefined in the 2nd element of your tuple via the split function or if the last element of the list was already undefined.

+10
source share

undefined no better than using error . In fact, undefined in foreplay is defined as

 undefined = error "Prelude.undefined" 


Now a function that cannot lead to error is called a "full function", i.e. Valid for all input values.

The split function that you currently implemented has a signature

 split :: [a] -> ([a], a) 

This is a problem because the signature of type promises is that the result always contains a list and an element, which is obviously impossible to provide for empty lists of a generic type.

The canonical way in Haskell to solve this problem is to change the type signature, which means that sometimes we don’t have a valid value for the second element.

 split :: [a] -> ([a], Maybe a) 

Now you can write the correct implementation for the case when 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 find the missing value by the pattern

 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 
+11
source share

The error function does nothing until it is evaluated, so you can do something like:

 split [] = ([], error "split: empty list") last' = snd . split 
+8
source share

From Haskell 2010 Language Report> Introduction # Values ​​and Types

Errors in Haskell are semantically equivalent to ⊥ ("bottom"). Technically, they are indistinguishable from the non-terminal, so the language does not contain a mechanism for detecting or influencing errors.

To be clear, undefined intended to embed ⊥ in your program and given that (as Shang pointed out) undefined is defined in terms of error , there is therefore a “no” mechanism for detecting or affecting undefined ".

+4
source share

Although Ingo's semantically correct answer if you use GHC, there is a way to use a couple of “unsafe” functions, which, although not entirely perfect, as if you passed it an IO type calculation that contains an exception will return True, it works. This is a bit of a hoax, though :).

 import Control.Exception import System.IO.Unsafe import Unsafe.Coerce isUndefined :: a -> Bool isUndefined x = unsafePerformIO $ catch ((unsafeCoerce x :: IO ()) >> return False) (const $ return True :: SomeException -> IO Bool) 

I know this is terrible, but it works nonetheless. It does not detect interruption though :)

+1
source share

All Articles