05-Via-Refined-Types.purs

module PartialFunctions.ViaRefinedTypes where

import Prelude

import Data.Either (Either(..))
{-
Rather than making our function take any `Int` as its second argument,
why not guarantee that the second argument is not a zero?

Thus, we can 'refine' our `Int` type using a newtype to insure
that it is non-zero:
-}

newtype NonZeroInt = NonZero Int

safeDivision :: Int -> NonZeroInt -> Int
safeDivision x (NonZero y) = x / y

{-
To create an instance of `NonZeroInt`, we still need to use
a function that verifies that our `Int` is really non-zero.
-}

mkNonZeroInt :: Int -> Either NonZeroIntError NonZeroInt
mkNonZeroInt 0 = Left IntWasZero
mkNonZeroInt x = Right x

data NonZeroIntError = IntWasZero

-- Then we'll make it printable to the screen
instance Show NonZeroIntError where
  show IntWasZero = "Error: the integer was 0."