1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
-- |
-- Module : Foundation.Partial
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : portable
--
-- Partial give a way to annotate your partial function with
-- a simple wrapper, which can only evaluated using 'fromPartial'
--
-- > fromPartial ( head [] )
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Foundation.Partial
( Partial
, PartialError
, partialError
, partial
, fromPartial
, head
, fromJust
, fromLeft
, fromRight
) where
import Basement.Compat.Base
import Basement.Compat.Identity
-- | Partialiality wrapper.
newtype Partial a = Partial (Identity a)
deriving (Functor, Applicative, Monad)
-- | An error related to the evaluation of a Partial value that failed.
--
-- it contains the name of the function and the reason for failure
data PartialError = PartialError [Char] [Char]
deriving (Show,Eq,Typeable)
instance Exception PartialError
-- | Throw an asynchronous PartialError
partialError :: [Char] -> [Char] -> a
partialError lbl exp = throw (PartialError lbl exp)
-- | Create a value that is partial. this can only be
-- unwrap using the 'fromPartial' function
partial :: a -> Partial a
partial = pure
-- | Dewrap a possible partial value
fromPartial :: Partial a -> a
fromPartial (Partial ida) = runIdentity ida
-- | Partial function to get the head of a list
head :: [a] -> Partial a
head l = partial $
case l of
[] -> partialError "head" "empty list"
x:_ -> x
-- | Partial function to grab the value inside a Maybe
fromJust :: Maybe a -> Partial a
fromJust x = partial $
case x of
Nothing -> partialError "fromJust" "Nothing"
Just y -> y
-- Grab the Right value of an Either
fromRight :: Either a b -> Partial b
fromRight x = partial $
case x of
Left _ -> partialError "fromRight" "Left"
Right a -> a
-- Grab the Left value of an Either
fromLeft :: Either a b -> Partial a
fromLeft x = partial $
case x of
Right _ -> partialError "fromLeft" "Right"
Left a -> a
|