Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why discarded values are () instead of ⊥ in Haskell?

Tags:

haskell

Howcome in Haskell, when there is a value that would be discarded, () is used instead of ?

Examples (can't really think of anything other than IO actions at the moment):

mapM_ :: (Monad m) => (a -> m b) -> [a] -> m ()
foldM_ :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m ()
writeFile :: FilePath -> String -> IO ()

Under strict evaluation, this makes perfect sense, but in Haskell, it only makes the domain bigger.

Perhaps there are "unused parameter" functions d -> a which are strict on d (where d is an unconstrained type parameter and does not appear free in a)? Ex: seq, const' x y = yseqx.


People also ask

What does () mean in Haskell?

() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .

Can a Haskell function return nothing?

No. However, you can have functions that return a trivial value. The () type has only one inhabitant, () .

What does /= in Haskell mean?

The /= operator means "is not equal". It's supposed to be reminiscent of the mathematical "≠" symbol (i.e., an equals sign with a diagonal line through it). Follow this answer to receive notifications.

What does apostrophe mean in Haskell?

This answer is not useful. Show activity on this post. In Haskell it is just another character to distinguish identifiers and the identifier is then called fold prime , but it is commonly used in the same way as it used in mathematics. Follow this answer to receive notifications.


1 Answers

I think this is because you need to specify the type of the value to be discarded. In Haskell-98, () is the obvious choice. And as long as you know the type is (), you may as well make the value () as well (presuming evaluation proceeds that far), just in case somebody tries to pattern-match on it or something. I think most programmers don't like introducing extra ⊥'s into code because it's just an extra trap to fall into. I certainly avoid it.

Instead of (), it is possible to create an uninhabited type (except by ⊥ of course).

{-# LANGUAGE EmptyDataDecls #-}

data Void

mapM_ :: (Monad m) => (a -> m b) -> [a] -> m Void

Now it's not even possible to pattern-match, because there's no Void constructor. I suspect the reason this isn't done more often is because it's not Haskell-98 compatible, as it requires the EmptyDataDecls extension.

Edit: you can't pattern-match on Void, but seq will ruin your day. Thanks to @sacundim for pointing this out.

like image 115
John L Avatar answered Oct 04 '22 11:10

John L