2
2
3
3
module Functora.Money
4
4
( module X ,
5
- MoneyRep ,
5
+ IntRep ,
6
6
MoneyTags ,
7
7
NewMoneyTags ,
8
8
Money ,
@@ -39,74 +39,69 @@ import Functora.Prelude
39
39
import Functora.Tags as X
40
40
import qualified Language.Haskell.TH.Syntax as TH
41
41
42
- type family MoneyRep sig where
43
- MoneyRep 'Signed = Integer
44
- MoneyRep 'Unsigned = Natural
45
-
46
- type MoneyTags (sig :: SignedOrUnsigned ) tags =
47
- ( GetTag sig tags ,
48
- Eq (MoneyRep sig ),
49
- Ord (MoneyRep sig ),
50
- Show (MoneyRep sig ),
51
- Read (MoneyRep sig ),
52
- Data (MoneyRep sig ),
53
- Integral (MoneyRep sig ),
54
- From (MoneyRep sig ) Integer ,
55
- Typeable sig ,
42
+ type IntRep tags = NewIntRep (GetKey SignedOrUnsigned tags )
43
+
44
+ type family NewIntRep sig where
45
+ NewIntRep 'Signed = Integer
46
+ NewIntRep 'Unsigned = Natural
47
+
48
+ type MoneyTags tags =
49
+ ( Eq (IntRep tags ),
50
+ Ord (IntRep tags ),
51
+ Show (IntRep tags ),
52
+ Read (IntRep tags ),
53
+ Data (IntRep tags ),
54
+ Integral (IntRep tags ),
55
+ From (IntRep tags ) Integer ,
56
+ Typeable (IntRep tags ),
56
57
Typeable tags
57
58
)
58
59
59
- type NewMoneyTags ( sig :: SignedOrUnsigned ) lhs rhs =
60
+ type NewMoneyTags lhs rhs =
60
61
( lhs ~ rhs ,
61
- MoneyTags sig lhs
62
+ MoneyTags lhs
62
63
)
63
64
64
65
data Money tags where
65
66
Money ::
66
- forall tags sig .
67
- ( MoneyTags sig tags
67
+ forall tags .
68
+ ( MoneyTags tags
68
69
) =>
69
- Ratio (MoneyRep sig ) ->
70
+ Ratio (IntRep tags ) ->
70
71
Money tags
71
72
72
73
deriving stock instance Eq (Money tags )
73
74
74
75
deriving stock instance Ord (Money tags )
75
76
76
- deriving stock instance (MoneyTags sig tags ) => Show (Money tags )
77
+ deriving stock instance (MoneyTags tags ) => Show (Money tags )
77
78
78
- deriving stock instance (MoneyTags sig tags ) => Read (Money tags )
79
+ deriving stock instance (MoneyTags tags ) => Read (Money tags )
79
80
80
- deriving stock instance (MoneyTags sig tags ) => Data (Money tags )
81
+ deriving stock instance (MoneyTags tags ) => Data (Money tags )
81
82
82
- unMoney ::
83
- forall tags sig .
84
- ( MoneyTags sig tags
85
- ) =>
86
- Money tags ->
87
- Ratio (MoneyRep sig )
83
+ unMoney :: Money tags -> Ratio (IntRep tags )
88
84
unMoney (Money x) = x
89
85
90
86
parseMoney ::
91
- forall str tags m sig rep .
87
+ forall str tags m .
92
88
( From str Text ,
93
89
Show str ,
94
90
Data str ,
95
- MonadThrow m ,
96
- MoneyTags sig tags ,
97
- rep ~ MoneyRep sig
91
+ MoneyTags tags ,
92
+ MonadThrow m
98
93
) =>
99
94
str ->
100
95
m (Money tags )
101
96
parseMoney =
102
97
fmap Money . parseRatio
103
98
104
99
data SomeMoney k tags
105
- = forall (tag :: k ) ( sig :: SignedOrUnsigned ) .
100
+ = forall (tag :: k ).
106
101
( SingI tag ,
107
102
Typeable tag ,
108
103
Typeable k ,
109
- MoneyTags sig (tags |+| tag )
104
+ MoneyTags (tags |+| tag )
110
105
) =>
111
106
SomeMoney
112
107
(Sing tag )
@@ -121,17 +116,19 @@ instance (TestEquality (Sing :: k -> Type)) => Eq (SomeMoney k tags) where
121
116
deriving stock instance Show (SomeMoney k tags )
122
117
123
118
newMoney ::
124
- forall tags sig .
125
- ( MoneyTags sig tags
119
+ forall tags .
120
+ ( MoneyTags tags
126
121
) =>
127
- Ratio (MoneyRep sig ) ->
122
+ Ratio (IntRep tags ) ->
128
123
Money tags
129
124
newMoney = Money
130
125
131
126
newUnsignedMoneyBOS ::
132
127
forall tags buy sell .
133
- ( NewMoneyTags 'Unsigned buy (tags |+| 'Unsigned |+| 'Buy),
134
- NewMoneyTags 'Unsigned sell (tags |+| 'Unsigned |+| 'Sell)
128
+ ( NewMoneyTags buy (tags |+| 'Unsigned |+| 'Buy),
129
+ NewMoneyTags sell (tags |+| 'Unsigned |+| 'Sell),
130
+ IntRep buy ~ Natural ,
131
+ IntRep sell ~ Natural
135
132
) =>
136
133
Rational ->
137
134
SomeMoney BuyOrSell (tags |+| 'Unsigned)
@@ -143,8 +140,10 @@ newUnsignedMoneyBOS raw
143
140
144
141
newUnsignedMoneyGOL ::
145
142
forall tags gain lose .
146
- ( NewMoneyTags 'Unsigned gain (tags |+| 'Unsigned |+| 'Gain),
147
- NewMoneyTags 'Unsigned lose (tags |+| 'Unsigned |+| 'Lose)
143
+ ( NewMoneyTags gain (tags |+| 'Unsigned |+| 'Gain),
144
+ NewMoneyTags lose (tags |+| 'Unsigned |+| 'Lose),
145
+ IntRep gain ~ Natural ,
146
+ IntRep lose ~ Natural
148
147
) =>
149
148
Rational ->
150
149
SomeMoney GainOrLose (tags |+| 'Unsigned)
@@ -155,21 +154,18 @@ newUnsignedMoneyGOL raw
155
154
uns = unsafeFrom @ Rational @ (Ratio Natural ) $ abs raw
156
155
157
156
newFeeRate ::
158
- forall prev sig next .
159
- ( NewMoneyTags sig next (prev |+| 'FeeRate)
157
+ forall prev next .
158
+ ( NewMoneyTags next (prev |+| 'FeeRate)
160
159
) =>
161
- Ratio (MoneyRep sig ) ->
160
+ Ratio (IntRep next ) ->
162
161
Money next
163
162
newFeeRate = Money
164
163
165
164
addFee ::
166
- forall fee amt sig tags .
167
- ( GetTag sig fee ,
168
- GetTag sig amt ,
169
- NewMoneyTags
170
- sig
171
- tags
172
- ((fee |-| sig |-| 'FeeRate) |&| (amt |-| 'Net |+| 'Gross))
165
+ forall fee amt tags .
166
+ ( IntRep fee ~ IntRep amt ,
167
+ IntRep fee ~ IntRep tags ,
168
+ NewMoneyTags tags (amt |-| 'Net |+| 'Gross)
173
169
) =>
174
170
Money fee ->
175
171
Money amt ->
@@ -178,12 +174,10 @@ addFee (Money fee) (Money amt) =
178
174
Money $ amt / (1 - fee)
179
175
180
176
deductFee ::
181
- ( GetTag sig fee ,
182
- GetTag sig amt ,
183
- NewMoneyTags
184
- sig
185
- tags
186
- ((fee |-| sig |-| 'FeeRate) |&| (amt |-| 'Gross |+| 'Net))
177
+ forall fee amt tags .
178
+ ( IntRep fee ~ IntRep amt ,
179
+ IntRep fee ~ IntRep tags ,
180
+ NewMoneyTags tags (amt |-| 'Gross |+| 'Net)
187
181
) =>
188
182
Money fee ->
189
183
Money amt ->
@@ -192,13 +186,10 @@ deductFee (Money fee) (Money amt) =
192
186
Money $ amt * (1 - fee)
193
187
194
188
exchangeMoney ::
195
- forall rate base quote sig .
196
- ( MoneyTags sig rate ,
197
- MoneyTags sig base ,
198
- NewMoneyTags
199
- sig
200
- quote
201
- ((rate |-| sig |-| 'QuotePerBase) |&| (base |-| 'Base |+| 'Quote))
189
+ forall rate base quote .
190
+ ( IntRep rate ~ IntRep base ,
191
+ IntRep rate ~ IntRep quote ,
192
+ NewMoneyTags quote (base |-| 'Base |+| 'Quote)
202
193
) =>
203
194
Money rate ->
204
195
Money base ->
@@ -207,13 +198,7 @@ exchangeMoney (Money rate) (Money base) =
207
198
Money $ rate * base
208
199
209
200
data Funds tags where
210
- Funds ::
211
- forall tags sig .
212
- ( MoneyTags sig tags
213
- ) =>
214
- Money tags ->
215
- CurrencyCode ->
216
- Funds tags
201
+ Funds :: Money tags -> CurrencyCode -> Funds tags
217
202
218
203
fundsMoneyAmount :: Funds tags -> Money tags
219
204
fundsMoneyAmount (Funds amt _) = amt
@@ -225,17 +210,21 @@ deriving stock instance Eq (Funds tags)
225
210
226
211
deriving stock instance Ord (Funds tags )
227
212
228
- deriving stock instance (MoneyTags sig tags ) => Show (Funds tags )
213
+ deriving stock instance (MoneyTags tags ) => Show (Funds tags )
229
214
230
- deriving stock instance (MoneyTags sig tags ) => Read (Funds tags )
215
+ deriving stock instance (MoneyTags tags ) => Read (Funds tags )
231
216
232
- deriving stock instance (MoneyTags sig tags ) => Data (Funds tags )
217
+ deriving stock instance (MoneyTags tags ) => Data (Funds tags )
233
218
234
219
unJsonRational :: A. Decoder Rational
235
- unJsonRational =
236
- toRational <$> A. scientific
220
+ unJsonRational = toRational <$> A. scientific
237
221
238
- unJsonMoney :: forall tags sig . (MoneyTags sig tags ) => A. Decoder (Money tags )
222
+ unJsonMoney ::
223
+ forall tags (sig :: SignedOrUnsigned ).
224
+ ( MoneyTags tags ,
225
+ GetTag sig tags
226
+ ) =>
227
+ A. Decoder (Money tags )
239
228
unJsonMoney = do
240
229
rat <- unJsonRational
241
230
case sing :: Sing sig of
@@ -245,18 +234,22 @@ unJsonMoney = do
245
234
$ tryFrom @ Rational @ (Ratio Natural ) rat
246
235
247
236
unJsonUnsignedMoneyBOS ::
248
- forall tags .
249
- ( MoneyTags 'Unsigned (tags |+| 'Unsigned |+| 'Buy),
250
- MoneyTags 'Unsigned (tags |+| 'Unsigned |+| 'Sell)
237
+ forall tags buy sell .
238
+ ( NewMoneyTags buy (tags |+| 'Unsigned |+| 'Buy),
239
+ NewMoneyTags sell (tags |+| 'Unsigned |+| 'Sell),
240
+ IntRep buy ~ Natural ,
241
+ IntRep sell ~ Natural
251
242
) =>
252
243
A. Decoder (SomeMoney BuyOrSell (tags |+| 'Unsigned))
253
244
unJsonUnsignedMoneyBOS =
254
245
newUnsignedMoneyBOS @ tags <$> unJsonRational
255
246
256
247
unJsonUnsignedMoneyGOL ::
257
- forall tags .
258
- ( MoneyTags 'Unsigned (tags |+| 'Unsigned |+| 'Gain),
259
- MoneyTags 'Unsigned (tags |+| 'Unsigned |+| 'Lose)
248
+ forall tags gain lose .
249
+ ( NewMoneyTags gain (tags |+| 'Unsigned |+| 'Gain),
250
+ NewMoneyTags lose (tags |+| 'Unsigned |+| 'Lose),
251
+ IntRep gain ~ Natural ,
252
+ IntRep lose ~ Natural
260
253
) =>
261
254
A. Decoder (SomeMoney GainOrLose (tags |+| 'Unsigned))
262
255
unJsonUnsignedMoneyGOL =
0 commit comments