Newer
Older
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{- | Conversion between types with a known level of safety. *Heavily* inspired
by `witch` (which has dependencies that make it hard for us to use just yet).
-}
module Tahoe.SDMF.Internal.Converting where
import Control.Monad.Fail (MonadFail)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import Data.Int (Int64)
import Data.Word (Word16, Word32, Word64, Word8)
-- | Precise, infallible conversion between two types.
class From a b where
from :: a -> b
-- | Precise, fallible conversion between two types.
class TryFrom a b m where
tryFrom ::
-- | An error message for context if the conversion fails.
String ->
-- | The value to convert.
a ->
m b
instance MonadFail m => TryFrom Int Word32 m where
tryFrom msg n
| n < 0 = fail msg
| n > maxWord32 = fail msg
| otherwise = pure $ fromIntegral n
where
maxWord32 = from @Word32 @Int maxBound
instance MonadFail m => TryFrom Int Word64 m where
tryFrom msg n
| n < 0 = fail msg
| otherwise = pure $ fromIntegral n
instance MonadFail m => TryFrom Int64 Word64 m where
tryFrom msg n
| n < 0 = fail msg
| otherwise = pure $ fromIntegral n
instance From Word16 Int where
from = fromIntegral
instance From Word8 Int where
from = fromIntegral
instance From Word8 Word16 where
from = fromIntegral
instance From Word32 Word64 where
from = fromIntegral
instance From Word32 Int where
from = fromIntegral
instance From Int64 Int where
from = fromIntegral
instance From Int Int64 where
from = fromIntegral
instance MonadFail m => TryFrom Word64 Int m where
tryFrom msg n
| n > maxInt = fail msg
| otherwise = pure $ fromIntegral n
where
maxInt = fromIntegral (maxBound :: Int) :: Word64
instance MonadFail m => TryFrom Word16 Word8 m where
tryFrom msg n
| n > maxWord8 = fail msg
| otherwise = pure $ fromIntegral n
where
maxWord8 = from @Word8 @Word16 maxBound
instance MonadFail m => TryFrom Word64 Int64 m where
tryFrom msg n
| n > maxInt64 = fail msg
| otherwise = pure $ fromIntegral n
where
maxInt64 = fromIntegral (maxBound :: Int64) :: Word64
{- | Like `from` but with the order of the input/output type parameters
reversed.
-}
into :: forall b a. From a b => a -> b
into = from
{- | Like `tryFrom` but with the order of the input/output type parameters
reverse.
-}
tryInto :: forall b a m. TryFrom a b m => String -> a -> m b
tryInto = tryFrom