Static typing and dynamic typing usually are offering `null` references as solution for the *not an object* problem. With strong-static typing systems, there are not `null` references, because there is nothing that can be treated as wild-card type, as `Object()` in Java and `void *` in C and C++ — everything have a type. So, there are some flow control structures allowing the programmer to handle the *not an object* problem using composite data types. Classical examples are the Maybe Monad and the Either Monad in Haskell. Both of them, allow you to control the behaviour of the program using a composite type to bind `null` reference requirements.

-- | The type of strict optional values. data Maybe a = Nothing | Just !a deriving (Eq, Ord, Show, Read)

Maybe is a composite data type with algebraic form which encapsulates a type instance or an empty instance called `Nothing`. It meets the Monad requirements since it has the curried form `* → *` and allows you to hide the real instance inside all Monadic operations of the encapsulated instance. How it is being used? Please review the following example.

module Main (main) where import Data.Maybe sum2 :: Maybe Int -> Maybe Int -> Maybe Int sum2 Nothing Nothing = Nothing sum2 Nothing n = Nothing sum2 n Nothing = Nothing sum2 (Just n) (Just m) = Just $ n + m main :: IO () main = let a = sum2 (Just 10) Nothing in print $ fromJust a

The example above receives a two composite `Maybe Int` variables and returns a `Maybe Int` instance. We can tell that the function above is *safe*, because it handles `null` references properly. Only with `Just !a` input variables it is executing the `sum2` operation, in other case, it preserves the `Nothing` instance. To make it safe, we can ask if the resulting output is really a valid variable that can be handled by `fromJust` function.

main :: IO () main = let a = sum2 (Just 10) Nothing in if isNothing a then print "Nothing" else print $ fromJust a

But there is no *not an object* reference *“until it is declared”*. So, this is a composite type of kind *Algebraic Data Type* due to its curried form. But there is another powerful composite type that allows you to encapsulate dual results, not as it is being made with the Maybe Monad, but with two type variables allowing the composition between two optional types, which is called Either Monad.

-- | The strict choice type. data Either a b = Left !a | Right !b deriving (Eq, Ord, Read, Show)

`Either` encapsulates the type variables `a` and `b`. For example, due to its strong-static typing nature, Haskell does not allow to operate between floating point numbers and integer numbers, so we need explicit transformation functions to operate on them. So, the following example `sum3` works with this approach and a type `* → * → *`.

module Main (main) where import Data.Either sum3 :: Either Int Float -> Either Int Float -> Either Int Float sum3 (Right a) (Left b) = Right $ a + fromIntegral b sum3 (Left a) (Right b) = Right $ fromIntegral a + b sum3 (Right a) (Right b) = Right $ a + b sum3 (Left a) (Left b) = Left $ a + b main :: IO () main = let a = sum3 (Right 0.1) (Right 0.2) in case a of Left n -> print $ "Left: " ++ show n Right n -> print $ "Right: " ++ show n

So, the `Either` data type on the example above is encapsulating the `Int` and `Float` types. And you can combine many composite types as you need, for example we can do another version handling `Either (Maybe Int) Float` and still it will be valid, allowing `null` references for the integer part of the composite type. So, the limit on `null` references is embedded in the language, and usage of null references or *not an object* instances depends exclusively on you. Just imagine the amount of errors that can be reduced with strong-static typing.