Skip to content

Commit 46f0999

Browse files
authored
Add Decode/Encode instances for Record, simplify module structure (#53)
* Add Decode/Encode instances for Record * Docs * Simplify the module structure * Update README * Better backwards-compatibility
1 parent ad56cb7 commit 46f0999

File tree

14 files changed

+655
-342
lines changed

14 files changed

+655
-342
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ First, define some data type and derive `Generic`:
2525
To encode JSON, use `genericEncodeJSON`:
2626

2727
```purescript
28-
> import Foreign.Class (class Encode, class Decode, encode, decode)
29-
> import Foreign.Generic (defaultOptions, genericDecodeJSON, genericEncodeJSON)
28+
> import Foreign.Generic (defaultOptions, genericEncodeJSON)
3029
3130
> opts = defaultOptions { unwrapSingleConstructors = true }
3231
@@ -37,7 +36,8 @@ To encode JSON, use `genericEncodeJSON`:
3736
And to decode JSON, use `genericDecodeJSON`:
3837

3938
```purescript
40-
> import Control.Monad.Except
39+
> import Control.Monad.Except (runExcept)
40+
> import Foreign.Generic (genericDecodeJSON)
4141
4242
> runExcept (genericDecodeJSON opts "{\"a\":1}" :: _ MyRecord)
4343
(Right (MyRecord { a: 1 }))
@@ -46,6 +46,9 @@ And to decode JSON, use `genericDecodeJSON`:
4646
Badly formed JSON will result in a useful error, which can be inspected or pretty-printed:
4747

4848
```purescript
49+
> import Data.Bifunctor (lmap)
50+
> import Foreign (renderForeignError)
51+
4952
> lmap (map renderForeignError) $ runExcept (genericDecodeJSON opts "{\"a\":\"abc\"}" :: _ MyRecord)
5053
(Left
5154
(NonEmptyList

generated-docs/Foreign/Class.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
## Module Foreign.Class
22

3+
This module is provided for backwards-compatibility with the old API.
4+
5+
It is liable to be removed in a future release.
6+
7+
8+
### Re-exported from Foreign.Generic.Class:
9+
310
#### `Decode`
411

512
``` purescript
@@ -33,9 +40,11 @@ Decode Char
3340
Decode Boolean
3441
Decode Number
3542
Decode Int
43+
(Decode a) => Decode (Identity a)
3644
(Decode a) => Decode (Array a)
3745
(Decode a) => Decode (Maybe a)
3846
(Decode v) => Decode (Object v)
47+
(RowToList r rl, DecodeRecord r rl) => Decode { | r }
3948
```
4049

4150
#### `Encode`
@@ -71,9 +80,10 @@ Encode Char
7180
Encode Boolean
7281
Encode Number
7382
Encode Int
83+
(Encode a) => Encode (Identity a)
7484
(Encode a) => Encode (Array a)
7585
(Encode a) => Encode (Maybe a)
7686
(Encode v) => Encode (Object v)
87+
(RowToList r rl, EncodeRecord r rl) => Encode { | r }
7788
```
7889

79-

generated-docs/Foreign/Generic.md

Lines changed: 193 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
## Module Foreign.Generic
22

3-
#### `defaultOptions`
4-
5-
``` purescript
6-
defaultOptions :: Options
7-
```
8-
9-
Default decoding/encoding options:
10-
11-
- Represent sum types as records with `tag` and `contents` fields
12-
- Unwrap single arguments
13-
- Don't unwrap single constructors
14-
- Use the constructor names as-is
15-
- Use the field names as-is
16-
173
#### `genericDecode`
184

195
``` purescript
@@ -63,3 +49,196 @@ genericEncodeJSON :: forall a rep. Generic a rep => GenericEncode rep => Options
6349
Write a value which has a `Generic` type as a JSON String
6450

6551

52+
### Re-exported from Foreign:
53+
54+
#### `ForeignError`
55+
56+
``` purescript
57+
data ForeignError
58+
= ForeignError String
59+
| TypeMismatch String String
60+
| ErrorAtIndex Int ForeignError
61+
| ErrorAtProperty String ForeignError
62+
```
63+
64+
A type for foreign type errors
65+
66+
##### Instances
67+
``` purescript
68+
Eq ForeignError
69+
Ord ForeignError
70+
Show ForeignError
71+
```
72+
73+
#### `Foreign`
74+
75+
``` purescript
76+
data Foreign :: Type
77+
```
78+
79+
A type for _foreign data_.
80+
81+
Foreign data is data from any external _unknown_ or _unreliable_
82+
source, for which it cannot be guaranteed that the runtime representation
83+
conforms to that of any particular type.
84+
85+
Suitable applications of `Foreign` are
86+
87+
- To represent responses from web services
88+
- To integrate with external JavaScript libraries.
89+
90+
#### `F`
91+
92+
``` purescript
93+
type F = Except MultipleErrors
94+
```
95+
96+
An error monad, used in this library to encode possible failures when
97+
dealing with foreign data.
98+
99+
The `Alt` instance for `Except` allows us to accumulate errors,
100+
unlike `Either`, which preserves only the last error.
101+
102+
### Re-exported from Foreign.Generic.Class:
103+
104+
#### `SumEncoding`
105+
106+
``` purescript
107+
data SumEncoding
108+
= TaggedObject { tagFieldName :: String, contentsFieldName :: String, constructorTagTransform :: String -> String }
109+
```
110+
111+
The encoding of sum types for your type.
112+
`TaggedObject`s will be encoded in the form `{ [tagFieldName]: "ConstructorTag", [contentsFieldName]: "Contents"}`.
113+
`constructorTagTransform` can be provided to transform the constructor tag to a form you use, e.g. `toLower`/`toUpper`.
114+
115+
#### `Options`
116+
117+
``` purescript
118+
type Options = { sumEncoding :: SumEncoding, unwrapSingleConstructors :: Boolean, unwrapSingleArguments :: Boolean, fieldTransform :: String -> String }
119+
```
120+
121+
Encoding/Decoding options which can be used to customize
122+
`Decode` and `Encode` instances which are derived via
123+
`Generic` (see `genericEncode` and `genericDecode`).
124+
125+
#### `Decode`
126+
127+
``` purescript
128+
class Decode a where
129+
decode :: Foreign -> F a
130+
```
131+
132+
The `Decode` class is used to generate decoding functions
133+
of the form `Foreign -> F a` using `generics-rep` deriving.
134+
135+
First, derive `Generic` for your data:
136+
137+
```purescript
138+
import Data.Generic.Rep
139+
140+
data MyType = MyType ...
141+
142+
derive instance genericMyType :: Generic MyType _
143+
```
144+
145+
You can then use the `genericDecode` and `genericDecodeJSON` functions
146+
to decode your foreign/JSON-encoded data.
147+
148+
##### Instances
149+
``` purescript
150+
Decode Void
151+
Decode Unit
152+
Decode Foreign
153+
Decode String
154+
Decode Char
155+
Decode Boolean
156+
Decode Number
157+
Decode Int
158+
(Decode a) => Decode (Identity a)
159+
(Decode a) => Decode (Array a)
160+
(Decode a) => Decode (Maybe a)
161+
(Decode v) => Decode (Object v)
162+
(RowToList r rl, DecodeRecord r rl) => Decode { | r }
163+
```
164+
165+
#### `Encode`
166+
167+
``` purescript
168+
class Encode a where
169+
encode :: a -> Foreign
170+
```
171+
172+
The `Encode` class is used to generate encoding functions
173+
of the form `a -> Foreign` using `generics-rep` deriving.
174+
175+
First, derive `Generic` for your data:
176+
177+
```purescript
178+
import Data.Generic.Rep
179+
180+
data MyType = MyType ...
181+
182+
derive instance genericMyType :: Generic MyType _
183+
```
184+
185+
You can then use the `genericEncode` and `genericEncodeJSON` functions
186+
to encode your data as JSON.
187+
188+
##### Instances
189+
``` purescript
190+
Encode Void
191+
Encode Unit
192+
Encode Foreign
193+
Encode String
194+
Encode Char
195+
Encode Boolean
196+
Encode Number
197+
Encode Int
198+
(Encode a) => Encode (Identity a)
199+
(Encode a) => Encode (Array a)
200+
(Encode a) => Encode (Maybe a)
201+
(Encode v) => Encode (Object v)
202+
(RowToList r rl, EncodeRecord r rl) => Encode { | r }
203+
```
204+
205+
#### `GenericDecode`
206+
207+
``` purescript
208+
class GenericDecode a
209+
```
210+
211+
##### Instances
212+
``` purescript
213+
GenericDecode NoConstructors
214+
(IsSymbol name, GenericDecodeArgs rep, GenericCountArgs rep) => GenericDecode (Constructor name rep)
215+
(GenericDecode a, GenericDecode b) => GenericDecode (Sum a b)
216+
```
217+
218+
#### `GenericEncode`
219+
220+
``` purescript
221+
class GenericEncode a
222+
```
223+
224+
##### Instances
225+
``` purescript
226+
GenericEncode NoConstructors
227+
(IsSymbol name, GenericEncodeArgs rep) => GenericEncode (Constructor name rep)
228+
(GenericEncode a, GenericEncode b) => GenericEncode (Sum a b)
229+
```
230+
231+
#### `defaultOptions`
232+
233+
``` purescript
234+
defaultOptions :: Options
235+
```
236+
237+
Default decoding/encoding options:
238+
239+
- Represent sum types as records with `tag` and `contents` fields
240+
- Unwrap single arguments
241+
- Don't unwrap single constructors
242+
- Use the constructor names as-is
243+
- Use the field names as-is
244+

0 commit comments

Comments
 (0)