/
ToMetadata.purs
91 lines (75 loc) · 3.2 KB
/
ToMetadata.purs
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
81
82
83
84
85
86
87
88
89
90
91
module Metadata.ToMetadata
( class ToMetadata
, toMetadata
, AnyToMetadata
, class AnyToMetadataClass
, anyToMetadata
) where
import Prelude
import Data.Array (fromFoldable) as Array
import Data.BigInt (BigInt)
import Data.Foldable (class Foldable)
import Data.Map (Map)
import Data.Map (catMaybes, fromFoldable, toUnfoldable) as Map
import Data.Maybe (Maybe(Just), fromJust)
import Data.NonEmpty (NonEmpty)
import Data.Profunctor.Strong ((***))
import Data.Tuple (Tuple(..))
import Partial.Unsafe (unsafePartial)
import Types.ByteArray (ByteArray)
import Types.Int (Int, fromBigInt) as Int
import Types.TransactionMetadata
( TransactionMetadatum(MetadataMap, MetadataList, Int, Bytes, Text)
)
--------------------------------------------------------------------------------
-- ToMetadata
--------------------------------------------------------------------------------
class ToMetadata (a :: Type) where
toMetadata :: a -> TransactionMetadatum
instance ToMetadata TransactionMetadatum where
toMetadata = identity
instance (Ord k, ToMetadata k) => ToMetadata (Map k AnyToMetadata) where
toMetadata =
toMetadata <<< Map.catMaybes <<< map (\(AnyToMetadata f) -> f toMetadata)
else instance (ToMetadata k, ToMetadata v) => ToMetadata (Map k v) where
toMetadata mp =
let
entries = Map.toUnfoldable mp :: Array (Tuple k v)
in
MetadataMap <<< Map.fromFoldable $
map (toMetadata *** toMetadata) entries
instance (Ord k, ToMetadata k) => ToMetadata (Array (Tuple k AnyToMetadata)) where
toMetadata = toMetadata <<< Map.fromFoldable
else instance (Ord k, ToMetadata k, ToMetadata v) => ToMetadata (Array (Tuple k v)) where
toMetadata = toMetadata <<< Map.fromFoldable
else instance ToMetadata a => ToMetadata (Array a) where
toMetadata = MetadataList <<< map toMetadata
instance (Foldable f, ToMetadata a) => ToMetadata (NonEmpty f a) where
toMetadata = toMetadata <<< Array.fromFoldable
instance ToMetadata Int.Int where
toMetadata = Int
-- FIXME: Come up with a type-safe error handling approach.
instance ToMetadata BigInt where
toMetadata bi =
unsafePartial $ Int $ fromJust $ Int.fromBigInt bi
instance ToMetadata ByteArray where
toMetadata = Bytes
instance ToMetadata String where
toMetadata = Text
--------------------------------------------------------------------------------
-- AnyToMetadata
--------------------------------------------------------------------------------
-- | Existential wrapper over `ToMetadata` constrained types that enables
-- | heterogeneous collections and is particularly useful when dealing with
-- | `Maybe` values. `TransactionMetadatum` doesn't provide a way to
-- | represent `Maybe` values, so the basic idea is to filter out all
-- | `Nothing`s during conversion (see `ToMetadata (Map k AnyToMetadata)`
-- | instance for reference).
newtype AnyToMetadata = AnyToMetadata
(forall (r :: Type). (forall (a :: Type). ToMetadata a => a -> r) -> Maybe r)
class AnyToMetadataClass (a :: Type) where
anyToMetadata :: a -> AnyToMetadata
instance ToMetadata a => AnyToMetadataClass (Maybe a) where
anyToMetadata a = AnyToMetadata \f -> f <$> a
else instance ToMetadata a => AnyToMetadataClass a where
anyToMetadata a = AnyToMetadata \f -> Just (f a)