File: Partial.hs

package info (click to toggle)
haskell-foundation 0.0.30-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 932 kB
  • sloc: haskell: 9,124; ansic: 570; makefile: 7
file content (80 lines) | stat: -rw-r--r-- 2,113 bytes parent folder | download | duplicates (4)
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