I read in learn you haskell that
Enum members are sequentially ordered types ... Types in this class: (), Bool, Char ...
Also it appears in some signatures:
putChar :: Char -> IO ()
It is very difficult to find info about it in Google as the answers refer to problems of the "common parentheses" (use in function calls, precedence problems and the like).
Therefore, what does the expression ()
means? Is it a type? What are variables of type ()
? What is used for and when is it needed?
When you use parentheses to set off material in a sentence, you say that the material is “in parenthesis.” Put something in parentheses if it's a comment, an afterthought, or additional information that is possibly interesting but not essential to the subject.
Parentheses also signify a break in thought, but they mark an addition of information rather than an interruption like dashes do. Rather than a surprise (like dashes), parentheses are a gentler insertion in your sentence.
Parentheses are smooth and curved ( ), brackets are square [ ], and braces are curly { }. In mathematics, they are mostly used for order of operations. The innermost parentheses are calculated first, followed by the brackets that form the next layer outwards, followed by braces that form a third layer outwards.
The most important thing to note here: When talking about the order of operations, "parentheses" just means that any calculations completely inside parentheses should be done first. e.g for 10 * (6 + 3), we add 6 and 3 first.
It is both a type and a value. ()
is a special type "pronounced" unit, and it has one value: ()
, also pronounced unit. It is essentially the same as the type void
in Java or C/C++. If you're familiar with Python, think of it as the NoneType
which has the singleton None
.
It is useful when you want to denote an action that doesn't return anything. It is most commonly used in the context of Monads, such as the IO
monad. For example, if you had the following function:
getVal :: IO Int
getVal = do
putStrLn "Enter an integer value:"
n <- getLine
return $ read n
And for some reason you decided that you just wanted to annoy the user and throw away the number they just passed in:
getValAnnoy :: IO ()
getValAnnoy = do
_ <- getVal
return () -- Returns nothing
However, return
is just a Monad
function, so we could abstract this a bit further
throwAwayResult :: Monad m => m a -> m ()
throwAwayResult action = do
_ <- action
return ()
Then
getValAnnoy = throwAwayResult getVal
However, you don't have to write this function yourself, it already exists in Control.Monad
as the function void
that is even less constraining and works on Functor
s:
void :: Functor f => f a -> f ()
void fa = fmap (const ()) fa
Why does it work on Functor
instead of Monad
? Well, for each Monad
instance, you can write the Functor
instance as
instance Monad m => Functor m where
fmap f m = m >>= return . f
But you can't make a Monad
out of every Functor
. It's like how a square is a rectangle but a rectangle isn't always a square, Monads form a subset of Functors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With