├── .gitignore ├── .travis.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── _config.yml ├── bundle.js ├── index.html ├── index.md ├── modules │ ├── ast.ts.md │ ├── haskell.ts.md │ ├── index.md │ ├── index.ts.md │ ├── model.ts.md │ └── printer.ts.md ├── prism.css └── style.css ├── dtslint ├── index.d.ts ├── index.ts ├── tsconfig.json └── tslint.json ├── examples ├── Constrained.ts ├── Either.ts ├── FooBarBaz.ts ├── Maybe.ts ├── NotAlignedNames.ts ├── Nullary.ts ├── Option.ts ├── State.ts ├── These.ts ├── Tree.ts ├── Tuple2.ts ├── User.ts ├── Writer.ts └── index.ts ├── generate-examples.ts ├── jest.config.js ├── package-lock.json ├── package.json ├── playground ├── index.tsx ├── tsconfig.json └── webpack.config.js ├── src ├── ast.ts ├── haskell.ts ├── index.ts ├── model.ts └── printer.ts ├── test ├── examples.ts ├── haskell.ts ├── helpers.ts ├── index.ts ├── model.ts ├── printer.ts └── tsconfig.json ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | node_modules 3 | lib 4 | dev 5 | coverage 6 | .cache 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./node_modules/typescript/lib", 3 | "prettier.printWidth": 120, 4 | "prettier.semi": false, 5 | "prettier.singleQuote": true, 6 | "tslint.enable": true 7 | } 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | > **Tags:** 4 | > 5 | > - [New Feature] 6 | > - [Bug Fix] 7 | > - [Breaking Change] 8 | > - [Documentation] 9 | > - [Internal] 10 | > - [Polish] 11 | > - [Experimental] 12 | 13 | **Note**: Gaps between patch versions are faulty/broken releases. 14 | **Note**: A feature tagged as Experimental is in a high state of flux, you're at risk of it changing without notice. 15 | 16 | # 0.4.0 17 | 18 | - **Breaking Change** 19 | - upgrade to `fp-ts@2.x`, `monocle-ts@2.x`, `parser-ts@0.6.x` (@gcanti) 20 | - options 21 | - remove encoding (@gcanti) 22 | - remove matcheeName (@gcanti) 23 | - make generated `fold` always lazy and data-last (@gcanti) 24 | 25 | # 0.3.1 26 | 27 | - **Bug Fix** 28 | - use parameter declarations when printing phantom fields, fix #16 (@gcanti) 29 | 30 | # 0.3.0 31 | 32 | - **Breaking Change** 33 | - upgrade to `fp-ts@1.14.x` (@gcanti) 34 | 35 | # 0.2.2 36 | 37 | - **New Feature** 38 | - generate setoid instance, closes #12 (@gcanti) 39 | 40 | # 0.2.1 41 | 42 | - **New Feature** 43 | - generate prisms, closes #10 (@gcanti) 44 | 45 | # 0.2.0 46 | 47 | - **Breaking Change** 48 | - model refactoring (@gcanti) 49 | - **New Feature** 50 | - add support for unit type (@gcanti) 51 | 52 | # 0.1.0 53 | 54 | - **Breaking Change** 55 | - rename `parser.ts` to `haskell.ts` (@gcanti) 56 | - **New Feature** 57 | - add support for `fp-ts` encoding (@gcanti) 58 | 59 | # 0.0.2 60 | 61 | - **Breaking Change** 62 | - `model.ts` is changed in order to support tuple types and function types (@gcanti) 63 | - **New Feature** 64 | - add support for tuple types (@gcanti) 65 | - add support for function types (@gcanti) 66 | 67 | # 0.0.1 68 | 69 | Initial release 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Giulio Canti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TypeScript code generation from a haskell-like syntax for ADT (algebraic data types) 2 | 3 | # Playground 4 | 5 | [A playground with a few examples](https://gcanti.github.io/fp-ts-codegen/) 6 | 7 | # Installation 8 | 9 | To install the stable version: 10 | 11 | ```sh 12 | npm install fp-ts-codegen 13 | ``` 14 | 15 | # Usage 16 | 17 | Signature 18 | 19 | ```ts 20 | function run(input: string, options: Options = defaultOptions): Either 21 | ``` 22 | 23 | Example 24 | 25 | ```ts 26 | import { run } from 'fp-ts-codegen' 27 | 28 | console.log(run('data Option A = None | Some A')) 29 | ``` 30 | 31 | Output 32 | 33 | ```ts 34 | /** type definition */ 35 | 36 | export type Option = 37 | | { 38 | readonly type: 'None' 39 | } 40 | | { 41 | readonly type: 'Some' 42 | readonly value0: A 43 | } 44 | 45 | /** constructors */ 46 | 47 | export const none: Option = { type: 'None' } 48 | 49 | export function some(value0: A): Option { 50 | return { type: 'Some', value0 } 51 | } 52 | 53 | /** pattern matching */ 54 | 55 | export function fold(onNone: () => R, onSome: (value0: A) => R): (fa: Option) => R { 56 | return fa => { 57 | switch (fa.type) { 58 | case 'None': 59 | return onNone() 60 | case 'Some': 61 | return onSome(fa.value0) 62 | } 63 | } 64 | } 65 | 66 | /** prisms */ 67 | 68 | import { Prism } from 'monocle-ts' 69 | 70 | export function _none(): Prism, Option> { 71 | return Prism.fromPredicate(s => s.type === 'None') 72 | } 73 | 74 | export function _some(): Prism, Option> { 75 | return Prism.fromPredicate(s => s.type === 'Some') 76 | } 77 | 78 | /** Eq instance */ 79 | 80 | import { Eq } from 'fp-ts/lib/Eq' 81 | 82 | export function getEq(eqSomeValue0: Eq): Eq> { 83 | return { 84 | equals: (x, y) => { 85 | if (x === y) { 86 | return true 87 | } 88 | if (x.type === 'None' && y.type === 'None') { 89 | return true 90 | } 91 | if (x.type === 'Some' && y.type === 'Some') { 92 | return eqSomeValue0.equals(x.value0, y.value0) 93 | } 94 | return false 95 | } 96 | } 97 | } 98 | ``` 99 | 100 | # Records 101 | 102 | Syntax: `{ name :: type }` 103 | 104 | Example 105 | 106 | Source 107 | 108 | ```haskell 109 | -- record ---v 110 | data User = User { name :: string, surname :: string } 111 | ``` 112 | 113 | Output 114 | 115 | ```ts 116 | export type User = { 117 | readonly type: 'User' 118 | readonly name: string 119 | readonly surname: string 120 | } 121 | 122 | export function user(name: string, surname: string): User { 123 | return { type: 'User', name, surname } 124 | } 125 | ``` 126 | 127 | # Tuples 128 | 129 | Syntax: `(type1, type2, ...types)` 130 | 131 | Example 132 | 133 | Source 134 | 135 | ```haskell 136 | -- tuple ---v 137 | data Tuple2 A B = Tuple2 (A, B) 138 | ``` 139 | 140 | Output 141 | 142 | ```ts 143 | export type Tuple2 = { 144 | readonly type: 'Tuple2' 145 | readonly value0: [A, B] 146 | } 147 | 148 | export function tuple2(value0: [A, B]): Tuple2 { 149 | return { type: 'Tuple2', value0 } 150 | } 151 | ``` 152 | 153 | # Constraints 154 | 155 | Syntax: `( :: )` 156 | 157 | Example 158 | 159 | Source 160 | 161 | ```haskell 162 | -- constraint ---v 163 | data Constrained (A :: string) = Fetching | GotData A 164 | ``` 165 | 166 | Output 167 | 168 | ```ts 169 | export type Constrained = 170 | | { 171 | readonly type: 'Fetching' 172 | } 173 | | { 174 | readonly type: 'GotData' 175 | readonly value0: A 176 | } 177 | ``` 178 | 179 | # Options 180 | 181 | ```ts 182 | // fp-ts-codegen/lib/ast module 183 | 184 | export interface Options { 185 | /** the name of the field used as tag */ 186 | tagName: string 187 | /** the name prefix used for pattern matching functions */ 188 | foldName: string 189 | /** 190 | * the pattern matching handlers can be expressed as positional arguments 191 | * or a single object literal `tag -> handler` 192 | */ 193 | handlersStyle: { type: 'positional' } | { type: 'record'; handlersName: string } 194 | } 195 | 196 | export const defaultOptions: Options = { 197 | tagName: '_tag', 198 | foldName: 'fold', 199 | handlersStyle: { type: 'positional' } 200 | } 201 | ``` 202 | 203 | ## Options management 204 | 205 | Example 206 | 207 | ```ts 208 | import { lenses, defaultOptions } from 'fp-ts-codegen/lib/ast' 209 | 210 | lenses.tagName.set('tag')(defaultOptions) 211 | /* 212 | { 213 | tagName: 'tag', 214 | foldName: 'fold', 215 | ... 216 | } 217 | */ 218 | ``` 219 | 220 | # Modules 221 | 222 | - `ast` module: internal model -> TypeScript AST 223 | - `model` module: internal model 224 | - `printer` module: internal model -> TypeScript code 225 | - `haskell` module: haskell-like syntax -> internal model 226 | - `index` module: haskell-like syntax -> TypeScript code 227 | 228 | # Roadmap 229 | 230 | - derive type class instances? (`Functor`, `Foldable`, etc...) 231 | - ??? 232 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pmarsceill/just-the-docs 2 | 3 | # Enable or disable the site search 4 | search_enabled: true 5 | 6 | # Aux links for the upper right navigation 7 | aux_links: 8 | 'fp-ts-codegen on GitHub': 9 | - 'https://github.com/gcanti/fp-ts-codegen' 10 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | fp-ts-codegen playground 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | nav_order: 1 4 | --- 5 | -------------------------------------------------------------------------------- /docs/modules/ast.ts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ast.ts 3 | nav_order: 1 4 | parent: Modules 5 | --- 6 | 7 | --- 8 | 9 |

Table of contents

10 | 11 | - [AST (interface)](#ast-interface) 12 | - [Options (interface)](#options-interface) 13 | - [defaultOptions (constant)](#defaultoptions-constant) 14 | - [lenses (constant)](#lenses-constant) 15 | - [constructors (function)](#constructors-function) 16 | - [data (function)](#data-function) 17 | - [eq (function)](#eq-function) 18 | - [fold (function)](#fold-function) 19 | - [prisms (function)](#prisms-function) 20 | 21 | --- 22 | 23 | # AST (interface) 24 | 25 | **Signature** 26 | 27 | ```ts 28 | export interface AST
extends R.Reader {} 29 | ``` 30 | 31 | Added in v0.4.0 32 | 33 | # Options (interface) 34 | 35 | **Signature** 36 | 37 | ```ts 38 | export interface Options { 39 | /** the name of the field used as tag */ 40 | tagName: string 41 | /** the name prefix used for pattern matching functions */ 42 | foldName: string 43 | /** 44 | * the pattern matching handlers can be expressed as positional arguments 45 | * or a single object literal `tag -> handler` 46 | */ 47 | handlersStyle: { type: 'positional' } | { type: 'record'; handlersName: string } 48 | } 49 | ``` 50 | 51 | Added in v0.4.0 52 | 53 | # defaultOptions (constant) 54 | 55 | **Signature** 56 | 57 | ```ts 58 | export const defaultOptions: Options = ... 59 | ``` 60 | 61 | Added in v0.4.0 62 | 63 | # lenses (constant) 64 | 65 | **Signature** 66 | 67 | ```ts 68 | export const lenses: { [K in keyof Options]: Lens } = ... 69 | ``` 70 | 71 | Added in v0.4.0 72 | 73 | # constructors (function) 74 | 75 | **Signature** 76 | 77 | ```ts 78 | export function constructors(d: M.Data): AST> { ... } 79 | ``` 80 | 81 | Added in v0.4.0 82 | 83 | # data (function) 84 | 85 | **Signature** 86 | 87 | ```ts 88 | export function data(d: M.Data): AST> { ... } 89 | ``` 90 | 91 | Added in v0.4.0 92 | 93 | # eq (function) 94 | 95 | **Signature** 96 | 97 | ```ts 98 | export function eq(d: M.Data): AST> { ... } 99 | ``` 100 | 101 | Added in v0.4.0 102 | 103 | # fold (function) 104 | 105 | **Signature** 106 | 107 | ```ts 108 | export function fold(d: M.Data): AST> { ... } 109 | ``` 110 | 111 | Added in v0.4.0 112 | 113 | # prisms (function) 114 | 115 | **Signature** 116 | 117 | ```ts 118 | export function prisms(d: M.Data): AST> { ... } 119 | ``` 120 | 121 | Added in v0.4.0 122 | -------------------------------------------------------------------------------- /docs/modules/haskell.ts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: haskell.ts 3 | nav_order: 2 4 | parent: Modules 5 | --- 6 | 7 | --- 8 | 9 |

Table of contents

10 | 11 | - [constructor (constant)](#constructor-constant) 12 | - [data (constant)](#data-constant) 13 | - [fun (constant)](#fun-constant) 14 | - [identifier (constant)](#identifier-constant) 15 | - [parameterDeclaration (constant)](#parameterdeclaration-constant) 16 | - [ref (constant)](#ref-constant) 17 | - [tuple (constant)](#tuple-constant) 18 | - [type (constant)](#type-constant) 19 | - [types (constant)](#types-constant) 20 | - [parse (function)](#parse-function) 21 | 22 | --- 23 | 24 | # constructor (constant) 25 | 26 | **Signature** 27 | 28 | ```ts 29 | export const constructor: P.Parser = ... 30 | ``` 31 | 32 | Added in v0.4.0 33 | 34 | # data (constant) 35 | 36 | **Signature** 37 | 38 | ```ts 39 | export const data: P.Parser = ... 40 | ``` 41 | 42 | Added in v0.4.0 43 | 44 | # fun (constant) 45 | 46 | **Signature** 47 | 48 | ```ts 49 | export const fun: P.Parser = ... 50 | ``` 51 | 52 | Added in v0.4.0 53 | 54 | # identifier (constant) 55 | 56 | **Signature** 57 | 58 | ```ts 59 | export const identifier: P.Parser = ... 60 | ``` 61 | 62 | Added in v0.4.0 63 | 64 | # parameterDeclaration (constant) 65 | 66 | **Signature** 67 | 68 | ```ts 69 | export const parameterDeclaration = ... 70 | ``` 71 | 72 | # ref (constant) 73 | 74 | **Signature** 75 | 76 | ```ts 77 | export const ref: P.Parser = ... 78 | ``` 79 | 80 | Added in v0.4.0 81 | 82 | # tuple (constant) 83 | 84 | **Signature** 85 | 86 | ```ts 87 | export const tuple: P.Parser = ... 88 | ``` 89 | 90 | Added in v0.4.0 91 | 92 | # type (constant) 93 | 94 | **Signature** 95 | 96 | ```ts 97 | export const type: P.Parser = ... 98 | ``` 99 | 100 | Added in v0.4.0 101 | 102 | # types (constant) 103 | 104 | **Signature** 105 | 106 | ```ts 107 | export const types: P.Parser> = ... 108 | ``` 109 | 110 | Added in v0.4.0 111 | 112 | # parse (function) 113 | 114 | **Signature** 115 | 116 | ```ts 117 | export function parse(s: string): Either { ... } 118 | ``` 119 | 120 | Added in v0.4.0 121 | -------------------------------------------------------------------------------- /docs/modules/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Modules 3 | has_children: true 4 | permalink: /docs/modules 5 | nav_order: 2 6 | --- 7 | -------------------------------------------------------------------------------- /docs/modules/index.ts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: index.ts 3 | nav_order: 3 4 | parent: Modules 5 | --- 6 | 7 | --- 8 | 9 |

Table of contents

10 | 11 | - [run (function)](#run-function) 12 | 13 | --- 14 | 15 | # run (function) 16 | 17 | **Signature** 18 | 19 | ```ts 20 | export function run(input: string, options: Options = defaultOptions): E.Either { ... } 21 | ``` 22 | 23 | Added in v0.4.0 24 | -------------------------------------------------------------------------------- /docs/modules/model.ts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: model.ts 3 | nav_order: 4 4 | parent: Modules 5 | --- 6 | 7 | --- 8 | 9 |

Table of contents

10 | 11 | - [Constructor (interface)](#constructor-interface) 12 | - [Data (interface)](#data-interface) 13 | - [Fun (interface)](#fun-interface) 14 | - [Member (interface)](#member-interface) 15 | - [ParameterDeclaration (interface)](#parameterdeclaration-interface) 16 | - [Ref (interface)](#ref-interface) 17 | - [Tuple (interface)](#tuple-interface) 18 | - [Unit (interface)](#unit-interface) 19 | - [Identifier (type alias)](#identifier-type-alias) 20 | - [Type (type alias)](#type-type-alias) 21 | - [unit (constant)](#unit-constant) 22 | - [constructor (function)](#constructor-function) 23 | - [data (function)](#data-function) 24 | - [fun (function)](#fun-function) 25 | - [isEnum (function)](#isenum-function) 26 | - [isNullary (function)](#isnullary-function) 27 | - [isPolymorphic (function)](#ispolymorphic-function) 28 | - [isRecursive (function)](#isrecursive-function) 29 | - [isRecursiveMember (function)](#isrecursivemember-function) 30 | - [isSum (function)](#issum-function) 31 | - [member (function)](#member-function) 32 | - [parameterDeclaration (function)](#parameterdeclaration-function) 33 | - [ref (function)](#ref-function) 34 | - [tuple (function)](#tuple-function) 35 | 36 | --- 37 | 38 | # Constructor (interface) 39 | 40 | **Signature** 41 | 42 | ```ts 43 | export interface Constructor { 44 | readonly name: Identifier 45 | readonly members: Array 46 | } 47 | ``` 48 | 49 | Added in v0.4.0 50 | 51 | # Data (interface) 52 | 53 | **Signature** 54 | 55 | ```ts 56 | export interface Data { 57 | readonly name: Identifier 58 | readonly parameterDeclarations: Array 59 | readonly constructors: NonEmptyArray 60 | } 61 | ``` 62 | 63 | Added in v0.4.0 64 | 65 | # Fun (interface) 66 | 67 | **Signature** 68 | 69 | ```ts 70 | export interface Fun { 71 | readonly kind: 'Fun' 72 | readonly domain: Type 73 | readonly codomain: Type 74 | } 75 | ``` 76 | 77 | Added in v0.4.0 78 | 79 | # Member (interface) 80 | 81 | **Signature** 82 | 83 | ```ts 84 | export interface Member { 85 | readonly type: Type 86 | readonly name: Option 87 | } 88 | ``` 89 | 90 | Added in v0.4.0 91 | 92 | # ParameterDeclaration (interface) 93 | 94 | **Signature** 95 | 96 | ```ts 97 | export interface ParameterDeclaration { 98 | readonly name: Identifier 99 | readonly constraint: Option 100 | } 101 | ``` 102 | 103 | Added in v0.4.0 104 | 105 | # Ref (interface) 106 | 107 | **Signature** 108 | 109 | ```ts 110 | export interface Ref { 111 | readonly kind: 'Ref' 112 | readonly name: Identifier 113 | readonly parameters: Array 114 | } 115 | ``` 116 | 117 | Added in v0.4.0 118 | 119 | # Tuple (interface) 120 | 121 | **Signature** 122 | 123 | ```ts 124 | export interface Tuple { 125 | readonly kind: 'Tuple' 126 | readonly types: Array 127 | } 128 | ``` 129 | 130 | Added in v0.4.0 131 | 132 | # Unit (interface) 133 | 134 | **Signature** 135 | 136 | ```ts 137 | export interface Unit { 138 | readonly kind: 'Unit' 139 | } 140 | ``` 141 | 142 | Added in v0.4.0 143 | 144 | # Identifier (type alias) 145 | 146 | **Signature** 147 | 148 | ```ts 149 | export type Identifier = string 150 | ``` 151 | 152 | Added in v0.4.0 153 | 154 | # Type (type alias) 155 | 156 | **Signature** 157 | 158 | ```ts 159 | export type Type = Ref | Tuple | Fun | Unit 160 | ``` 161 | 162 | Added in v0.4.0 163 | 164 | # unit (constant) 165 | 166 | **Signature** 167 | 168 | ```ts 169 | export const unit: Type = ... 170 | ``` 171 | 172 | Added in v0.4.0 173 | 174 | # constructor (function) 175 | 176 | **Signature** 177 | 178 | ```ts 179 | export function constructor(name: Identifier, members: Array = []): Constructor { ... } 180 | ``` 181 | 182 | Added in v0.4.0 183 | 184 | # data (function) 185 | 186 | **Signature** 187 | 188 | ```ts 189 | export function data( 190 | name: Identifier, 191 | parameterDeclarations: Array, 192 | constructors: NonEmptyArray 193 | ): Data { ... } 194 | ``` 195 | 196 | Added in v0.4.0 197 | 198 | # fun (function) 199 | 200 | **Signature** 201 | 202 | ```ts 203 | export function fun(domain: Type, codomain: Type): Type { ... } 204 | ``` 205 | 206 | Added in v0.4.0 207 | 208 | # isEnum (function) 209 | 210 | **Signature** 211 | 212 | ```ts 213 | export function isEnum(d: Data): boolean { ... } 214 | ``` 215 | 216 | Added in v0.4.0 217 | 218 | # isNullary (function) 219 | 220 | **Signature** 221 | 222 | ```ts 223 | export function isNullary(c: Constructor): boolean { ... } 224 | ``` 225 | 226 | Added in v0.4.0 227 | 228 | # isPolymorphic (function) 229 | 230 | **Signature** 231 | 232 | ```ts 233 | export function isPolymorphic(d: Data): boolean { ... } 234 | ``` 235 | 236 | Added in v0.4.0 237 | 238 | # isRecursive (function) 239 | 240 | **Signature** 241 | 242 | ```ts 243 | export function isRecursive(d: Data): boolean { ... } 244 | ``` 245 | 246 | Added in v0.4.0 247 | 248 | # isRecursiveMember (function) 249 | 250 | **Signature** 251 | 252 | ```ts 253 | export function isRecursiveMember(m: Member, d: Data): boolean { ... } 254 | ``` 255 | 256 | Added in v0.4.0 257 | 258 | # isSum (function) 259 | 260 | **Signature** 261 | 262 | ```ts 263 | export function isSum(d: Data): boolean { ... } 264 | ``` 265 | 266 | Added in v0.4.0 267 | 268 | # member (function) 269 | 270 | **Signature** 271 | 272 | ```ts 273 | export function member(type: Type, name: Option = none): Member { ... } 274 | ``` 275 | 276 | Added in v0.4.0 277 | 278 | # parameterDeclaration (function) 279 | 280 | **Signature** 281 | 282 | ```ts 283 | export function parameterDeclaration(name: Identifier, constraint: Option = none): ParameterDeclaration { ... } 284 | ``` 285 | 286 | Added in v0.4.0 287 | 288 | # ref (function) 289 | 290 | **Signature** 291 | 292 | ```ts 293 | export function ref(name: Identifier, parameters: Array = []): Type { ... } 294 | ``` 295 | 296 | Added in v0.4.0 297 | 298 | # tuple (function) 299 | 300 | **Signature** 301 | 302 | ```ts 303 | export function tuple(types: Array): Type { ... } 304 | ``` 305 | 306 | Added in v0.4.0 307 | -------------------------------------------------------------------------------- /docs/modules/printer.ts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: printer.ts 3 | nav_order: 5 4 | parent: Modules 5 | --- 6 | 7 | --- 8 | 9 |

Table of contents

10 | 11 | - [Printer (interface)](#printer-interface) 12 | - [all (function)](#all-function) 13 | - [ast (function)](#ast-function) 14 | - [constructors (function)](#constructors-function) 15 | - [data (function)](#data-function) 16 | - [eq (function)](#eq-function) 17 | - [fold (function)](#fold-function) 18 | - [getMonoid (function)](#getmonoid-function) 19 | - [print (function)](#print-function) 20 | - [prisms (function)](#prisms-function) 21 | 22 | --- 23 | 24 | # Printer (interface) 25 | 26 | **Signature** 27 | 28 | ```ts 29 | export interface Printer
extends R.Reader {} 30 | ``` 31 | 32 | Added in v0.4.0 33 | 34 | # all (function) 35 | 36 | **Signature** 37 | 38 | ```ts 39 | export function all(d: M.Data): Printer> { ... } 40 | ``` 41 | 42 | Added in v0.4.0 43 | 44 | # ast (function) 45 | 46 | **Signature** 47 | 48 | ```ts 49 | export function ast(ast: ts.Node): string { ... } 50 | ``` 51 | 52 | Added in v0.4.0 53 | 54 | # constructors (function) 55 | 56 | **Signature** 57 | 58 | ```ts 59 | export function constructors(d: M.Data): Printer> { ... } 60 | ``` 61 | 62 | Added in v0.4.0 63 | 64 | # data (function) 65 | 66 | **Signature** 67 | 68 | ```ts 69 | export function data(d: M.Data): Printer { ... } 70 | ``` 71 | 72 | Added in v0.4.0 73 | 74 | # eq (function) 75 | 76 | **Signature** 77 | 78 | ```ts 79 | export function eq(d: M.Data): Printer> { ... } 80 | ``` 81 | 82 | Added in v0.4.0 83 | 84 | # fold (function) 85 | 86 | **Signature** 87 | 88 | ```ts 89 | export function fold(d: M.Data): Printer { ... } 90 | ``` 91 | 92 | Added in v0.4.0 93 | 94 | # getMonoid (function) 95 | 96 | **Signature** 97 | 98 | ```ts 99 | export function getMonoid(M: Mon.Monoid): Mon.Monoid> { ... } 100 | ``` 101 | 102 | Added in v0.4.0 103 | 104 | # print (function) 105 | 106 | **Signature** 107 | 108 | ```ts 109 | export function print(options: Ast.Options): (d: M.Data) => string { ... } 110 | ``` 111 | 112 | Added in v0.4.0 113 | 114 | # prisms (function) 115 | 116 | **Signature** 117 | 118 | ```ts 119 | export function prisms(d: M.Data): Printer> { ... } 120 | ``` 121 | 122 | Added in v0.4.0 123 | -------------------------------------------------------------------------------- /docs/prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.15.0 2 | https://prismjs.com/download.html#themes=prism&languages=clike+javascript+typescript */ 3 | /** 4 | * prism.js default theme for JavaScript, CSS and HTML 5 | * Based on dabblet (http://dabblet.com) 6 | * @author Lea Verou 7 | */ 8 | 9 | code[class*="language-"], 10 | pre[class*="language-"] { 11 | color: black; 12 | background: none; 13 | text-shadow: 0 1px white; 14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 15 | text-align: left; 16 | white-space: pre; 17 | word-spacing: normal; 18 | word-break: normal; 19 | word-wrap: normal; 20 | line-height: 1.5; 21 | 22 | -moz-tab-size: 4; 23 | -o-tab-size: 4; 24 | tab-size: 4; 25 | 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | } 31 | 32 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 33 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 34 | text-shadow: none; 35 | background: #b3d4fc; 36 | } 37 | 38 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 39 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 40 | text-shadow: none; 41 | background: #b3d4fc; 42 | } 43 | 44 | @media print { 45 | code[class*="language-"], 46 | pre[class*="language-"] { 47 | text-shadow: none; 48 | } 49 | } 50 | 51 | /* Code blocks */ 52 | pre[class*="language-"] { 53 | padding: 1em; 54 | margin: .5em 0; 55 | overflow: auto; 56 | } 57 | 58 | :not(pre) > code[class*="language-"], 59 | pre[class*="language-"] { 60 | background: #f5f2f0; 61 | } 62 | 63 | /* Inline code */ 64 | :not(pre) > code[class*="language-"] { 65 | padding: .1em; 66 | border-radius: .3em; 67 | white-space: normal; 68 | } 69 | 70 | .token.comment, 71 | .token.prolog, 72 | .token.doctype, 73 | .token.cdata { 74 | color: slategray; 75 | } 76 | 77 | .token.punctuation { 78 | color: #999; 79 | } 80 | 81 | .namespace { 82 | opacity: .7; 83 | } 84 | 85 | .token.property, 86 | .token.tag, 87 | .token.boolean, 88 | .token.number, 89 | .token.constant, 90 | .token.symbol, 91 | .token.deleted { 92 | color: #905; 93 | } 94 | 95 | .token.selector, 96 | .token.attr-name, 97 | .token.string, 98 | .token.char, 99 | .token.builtin, 100 | .token.inserted { 101 | color: #690; 102 | } 103 | 104 | .token.operator, 105 | .token.entity, 106 | .token.url, 107 | .language-css .token.string, 108 | .style .token.string { 109 | color: #9a6e3a; 110 | background: hsla(0, 0%, 100%, .5); 111 | } 112 | 113 | .token.atrule, 114 | .token.attr-value, 115 | .token.keyword { 116 | color: #07a; 117 | } 118 | 119 | .token.function, 120 | .token.class-name { 121 | color: #DD4A68; 122 | } 123 | 124 | .token.regex, 125 | .token.important, 126 | .token.variable { 127 | color: #e90; 128 | } 129 | 130 | .token.important, 131 | .token.bold { 132 | font-weight: bold; 133 | } 134 | .token.italic { 135 | font-style: italic; 136 | } 137 | 138 | .token.entity { 139 | cursor: help; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Fira code', monospace; 3 | } 4 | 5 | table td { 6 | vertical-align: top; 7 | padding: 20px; 8 | } 9 | 10 | table td.source { 11 | width: 40%; 12 | } 13 | 14 | table td.code { 15 | width: 60%; 16 | } 17 | 18 | textarea { 19 | font-family: 'Fira code', monospace; 20 | width: 100%; 21 | border: none; 22 | font-size: 16px; 23 | padding: 10px; 24 | } 25 | 26 | select { 27 | font-size: 16px; 28 | } 29 | -------------------------------------------------------------------------------- /dtslint/index.d.ts: -------------------------------------------------------------------------------- 1 | // TypeScript Version: 3.0 2 | -------------------------------------------------------------------------------- /dtslint/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcanti/fp-ts-codegen/40a70dc17724a594fb191dd37c192633d1ed4412/dtslint/index.ts -------------------------------------------------------------------------------- /dtslint/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true, 4 | "strict": true, 5 | "noImplicitAny": true, 6 | "noImplicitThis": true, 7 | "strictNullChecks": true, 8 | "strictFunctionTypes": true, 9 | "noImplicitReturns": false, 10 | "noUnusedLocals": false, 11 | "noUnusedParameters": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "target": "es5", 14 | "lib": ["es2015"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dtslint/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "dtslint/dtslint.json", 3 | "rules": { 4 | "semicolon": false, 5 | "array-type": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/Constrained.ts: -------------------------------------------------------------------------------- 1 | export type Constrained = { 2 | readonly type: "Fetching"; 3 | } | { 4 | readonly type: "GotData"; 5 | readonly value0: A; 6 | }; 7 | 8 | export const fetching: Constrained = { type: "Fetching" }; 9 | 10 | export function gotData(value0: A): Constrained { return { type: "GotData", value0 }; } 11 | 12 | export function fold(onFetching: () => R, onGotData: (value0: A) => R): (fa: Constrained) => R { return fa => { switch (fa.type) { 13 | case "Fetching": return onFetching(); 14 | case "GotData": return onGotData(fa.value0); 15 | } }; } 16 | 17 | import { Prism } from "monocle-ts"; 18 | 19 | export function _fetching(): Prism, Constrained> { return Prism.fromPredicate(s => s.type === "Fetching"); } 20 | 21 | export function _gotData(): Prism, Constrained> { return Prism.fromPredicate(s => s.type === "GotData"); } 22 | 23 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 24 | 25 | export function getEq(eqGotDataValue0: Eq): Eq> { return fromEquals((x, y) => { if (x.type === "Fetching" && y.type === "Fetching") { 26 | return true; 27 | } if (x.type === "GotData" && y.type === "GotData") { 28 | return eqGotDataValue0.equals(x.value0, y.value0); 29 | } return false; }); } 30 | 31 | -------------------------------------------------------------------------------- /examples/Either.ts: -------------------------------------------------------------------------------- 1 | export type Either = { 2 | readonly type: "Left"; 3 | readonly value0: E; 4 | } | { 5 | readonly type: "Right"; 6 | readonly value0: R; 7 | }; 8 | 9 | export function left(value0: E): Either { return { type: "Left", value0 }; } 10 | 11 | export function right(value0: R): Either { return { type: "Right", value0 }; } 12 | 13 | export function fold(onLeft: (value0: E) => R1, onRight: (value0: R) => R1): (fa: Either) => R1 { return fa => { switch (fa.type) { 14 | case "Left": return onLeft(fa.value0); 15 | case "Right": return onRight(fa.value0); 16 | } }; } 17 | 18 | import { Prism } from "monocle-ts"; 19 | 20 | export function _left(): Prism, Either> { return Prism.fromPredicate(s => s.type === "Left"); } 21 | 22 | export function _right(): Prism, Either> { return Prism.fromPredicate(s => s.type === "Right"); } 23 | 24 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 25 | 26 | export function getEq(eqLeftValue0: Eq, eqRightValue0: Eq): Eq> { return fromEquals((x, y) => { if (x.type === "Left" && y.type === "Left") { 27 | return eqLeftValue0.equals(x.value0, y.value0); 28 | } if (x.type === "Right" && y.type === "Right") { 29 | return eqRightValue0.equals(x.value0, y.value0); 30 | } return false; }); } 31 | 32 | -------------------------------------------------------------------------------- /examples/FooBarBaz.ts: -------------------------------------------------------------------------------- 1 | export type FooBarBaz = { 2 | readonly type: "Foo"; 3 | } | { 4 | readonly type: "Bar"; 5 | } | { 6 | readonly type: "Baz"; 7 | }; 8 | 9 | export const foo: FooBarBaz = { type: "Foo" }; 10 | 11 | export const bar: FooBarBaz = { type: "Bar" }; 12 | 13 | export const baz: FooBarBaz = { type: "Baz" }; 14 | 15 | export function fold(onFoo: () => R, onBar: () => R, onBaz: () => R): (fa: FooBarBaz) => R { return fa => { switch (fa.type) { 16 | case "Foo": return onFoo(); 17 | case "Bar": return onBar(); 18 | case "Baz": return onBaz(); 19 | } }; } 20 | 21 | import { Prism } from "monocle-ts"; 22 | 23 | export const _Foo: Prism = Prism.fromPredicate(s => s.type === "Foo"); 24 | 25 | export const _Bar: Prism = Prism.fromPredicate(s => s.type === "Bar"); 26 | 27 | export const _Baz: Prism = Prism.fromPredicate(s => s.type === "Baz"); 28 | 29 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 30 | 31 | export function getEq(): Eq { return fromEquals((x, y) => { if (x.type === "Foo" && y.type === "Foo") { 32 | return true; 33 | } if (x.type === "Bar" && y.type === "Bar") { 34 | return true; 35 | } if (x.type === "Baz" && y.type === "Baz") { 36 | return true; 37 | } return false; }); } 38 | 39 | -------------------------------------------------------------------------------- /examples/Maybe.ts: -------------------------------------------------------------------------------- 1 | export type Maybe = { 2 | readonly type: "Nothing"; 3 | } | { 4 | readonly type: "Just"; 5 | readonly value: A; 6 | }; 7 | 8 | export const nothing: Maybe = { type: "Nothing" }; 9 | 10 | export function just(value: A): Maybe { return { type: "Just", value }; } 11 | 12 | export function fold(onNothing: () => R, onJust: (value: A) => R): (fa: Maybe) => R { return fa => { switch (fa.type) { 13 | case "Nothing": return onNothing(); 14 | case "Just": return onJust(fa.value); 15 | } }; } 16 | 17 | import { Prism } from "monocle-ts"; 18 | 19 | export function _nothing(): Prism, Maybe> { return Prism.fromPredicate(s => s.type === "Nothing"); } 20 | 21 | export function _just(): Prism, Maybe> { return Prism.fromPredicate(s => s.type === "Just"); } 22 | 23 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 24 | 25 | export function getEq(eqJustValue: Eq): Eq> { return fromEquals((x, y) => { if (x.type === "Nothing" && y.type === "Nothing") { 26 | return true; 27 | } if (x.type === "Just" && y.type === "Just") { 28 | return eqJustValue.equals(x.value, y.value); 29 | } return false; }); } 30 | 31 | -------------------------------------------------------------------------------- /examples/NotAlignedNames.ts: -------------------------------------------------------------------------------- 1 | export type NotAlignedNames = { 2 | readonly value: string; 3 | }; 4 | 5 | export function ctor(value: string): NotAlignedNames { return { value }; } 6 | 7 | 8 | 9 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 10 | 11 | export function getEq(eqValue: Eq): Eq { return fromEquals((x, y) => { return eqValue.equals(x.value, y.value); }); } 12 | 13 | -------------------------------------------------------------------------------- /examples/Nullary.ts: -------------------------------------------------------------------------------- 1 | export type Nullary = {}; 2 | 3 | export const nullary: Nullary = {}; 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/Option.ts: -------------------------------------------------------------------------------- 1 | export type Option = { 2 | readonly type: "None"; 3 | } | { 4 | readonly type: "Some"; 5 | readonly value0: A; 6 | }; 7 | 8 | export const none: Option = { type: "None" }; 9 | 10 | export function some(value0: A): Option { return { type: "Some", value0 }; } 11 | 12 | export function fold(onNone: () => R, onSome: (value0: A) => R): (fa: Option) => R { return fa => { switch (fa.type) { 13 | case "None": return onNone(); 14 | case "Some": return onSome(fa.value0); 15 | } }; } 16 | 17 | import { Prism } from "monocle-ts"; 18 | 19 | export function _none(): Prism, Option> { return Prism.fromPredicate(s => s.type === "None"); } 20 | 21 | export function _some(): Prism, Option> { return Prism.fromPredicate(s => s.type === "Some"); } 22 | 23 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 24 | 25 | export function getEq(eqSomeValue0: Eq): Eq> { return fromEquals((x, y) => { if (x.type === "None" && y.type === "None") { 26 | return true; 27 | } if (x.type === "Some" && y.type === "Some") { 28 | return eqSomeValue0.equals(x.value0, y.value0); 29 | } return false; }); } 30 | 31 | -------------------------------------------------------------------------------- /examples/State.ts: -------------------------------------------------------------------------------- 1 | export type State = { 2 | readonly value0: (s: S) => [A, S]; 3 | }; 4 | 5 | export function state(value0: (s: S) => [A, S]): State { return { value0 }; } 6 | 7 | 8 | 9 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 10 | 11 | export function getEq(eqValue0: Eq<(s: S) => [A, S]>): Eq> { return fromEquals((x, y) => { return eqValue0.equals(x.value0, y.value0); }); } 12 | 13 | -------------------------------------------------------------------------------- /examples/These.ts: -------------------------------------------------------------------------------- 1 | export type These = { 2 | readonly type: "Left"; 3 | readonly left: A; 4 | } | { 5 | readonly type: "Right"; 6 | readonly right: B; 7 | } | { 8 | readonly type: "Both"; 9 | readonly left: A; 10 | readonly right: B; 11 | }; 12 | 13 | export function left(left: A): These { return { type: "Left", left }; } 14 | 15 | export function right(right: B): These { return { type: "Right", right }; } 16 | 17 | export function both(left: A, right: B): These { return { type: "Both", left, right }; } 18 | 19 | export function fold(onLeft: (left: A) => R, onRight: (right: B) => R, onBoth: (left: A, right: B) => R): (fa: These) => R { return fa => { switch (fa.type) { 20 | case "Left": return onLeft(fa.left); 21 | case "Right": return onRight(fa.right); 22 | case "Both": return onBoth(fa.left, fa.right); 23 | } }; } 24 | 25 | import { Prism } from "monocle-ts"; 26 | 27 | export function _left(): Prism, These> { return Prism.fromPredicate(s => s.type === "Left"); } 28 | 29 | export function _right(): Prism, These> { return Prism.fromPredicate(s => s.type === "Right"); } 30 | 31 | export function _both(): Prism, These> { return Prism.fromPredicate(s => s.type === "Both"); } 32 | 33 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 34 | 35 | export function getEq(eqLeftLeft: Eq, eqRightRight: Eq, eqBothLeft: Eq, eqBothRight: Eq): Eq> { return fromEquals((x, y) => { if (x.type === "Left" && y.type === "Left") { 36 | return eqLeftLeft.equals(x.left, y.left); 37 | } if (x.type === "Right" && y.type === "Right") { 38 | return eqRightRight.equals(x.right, y.right); 39 | } if (x.type === "Both" && y.type === "Both") { 40 | return eqBothLeft.equals(x.left, y.left) && eqBothRight.equals(x.right, y.right); 41 | } return false; }); } 42 | 43 | -------------------------------------------------------------------------------- /examples/Tree.ts: -------------------------------------------------------------------------------- 1 | export type Tree = { 2 | readonly type: "Leaf"; 3 | } | { 4 | readonly type: "Node"; 5 | readonly value0: Tree; 6 | readonly value1: A; 7 | readonly value2: Tree; 8 | }; 9 | 10 | export const leaf: Tree = { type: "Leaf" }; 11 | 12 | export function node(value0: Tree, value1: A, value2: Tree): Tree { return { type: "Node", value0, value1, value2 }; } 13 | 14 | export function fold(onLeaf: () => R, onNode: (value0: Tree, value1: A, value2: Tree) => R): (fa: Tree) => R { return fa => { switch (fa.type) { 15 | case "Leaf": return onLeaf(); 16 | case "Node": return onNode(fa.value0, fa.value1, fa.value2); 17 | } }; } 18 | 19 | import { Prism } from "monocle-ts"; 20 | 21 | export function _leaf(): Prism, Tree> { return Prism.fromPredicate(s => s.type === "Leaf"); } 22 | 23 | export function _node(): Prism, Tree> { return Prism.fromPredicate(s => s.type === "Node"); } 24 | 25 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 26 | 27 | export function getEq(eqNodeValue1: Eq): Eq> { const S: Eq> = fromEquals((x, y) => { if (x.type === "Leaf" && y.type === "Leaf") { 28 | return true; 29 | } if (x.type === "Node" && y.type === "Node") { 30 | return S.equals(x.value0, y.value0) && eqNodeValue1.equals(x.value1, y.value1) && S.equals(x.value2, y.value2); 31 | } return false; }); return S; } 32 | 33 | -------------------------------------------------------------------------------- /examples/Tuple2.ts: -------------------------------------------------------------------------------- 1 | export type Tuple2 = { 2 | readonly value0: [A, B]; 3 | }; 4 | 5 | export function tuple2(value0: [A, B]): Tuple2 { return { value0 }; } 6 | 7 | 8 | 9 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 10 | 11 | export function getEq(eqValue0: Eq<[A, B]>): Eq> { return fromEquals((x, y) => { return eqValue0.equals(x.value0, y.value0); }); } 12 | 13 | -------------------------------------------------------------------------------- /examples/User.ts: -------------------------------------------------------------------------------- 1 | export type User = { 2 | readonly name: string; 3 | readonly surname: string; 4 | readonly age: number; 5 | }; 6 | 7 | export function user(name: string, surname: string, age: number): User { return { name, surname, age }; } 8 | 9 | 10 | 11 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 12 | 13 | export function getEq(eqName: Eq, eqSurname: Eq, eqAge: Eq): Eq { return fromEquals((x, y) => { return eqName.equals(x.name, y.name) && eqSurname.equals(x.surname, y.surname) && eqAge.equals(x.age, y.age); }); } 14 | 15 | -------------------------------------------------------------------------------- /examples/Writer.ts: -------------------------------------------------------------------------------- 1 | export type Writer = { 2 | readonly value0: () => [A, W]; 3 | }; 4 | 5 | export function writer(value0: () => [A, W]): Writer { return { value0 }; } 6 | 7 | 8 | 9 | import { Eq, fromEquals } from "fp-ts/lib/Eq"; 10 | 11 | export function getEq(eqValue0: Eq<() => [A, W]>): Eq> { return fromEquals((x, y) => { return eqValue0.equals(x.value0, y.value0); }); } 12 | 13 | -------------------------------------------------------------------------------- /examples/index.ts: -------------------------------------------------------------------------------- 1 | import './Option' 2 | import './Maybe' 3 | import './Either' 4 | import './These' 5 | import './Tree' 6 | import './FooBarBaz' 7 | import './User' 8 | import './Constrained' 9 | import './Tuple2' 10 | import './State' 11 | import './Writer' 12 | import './Nullary' 13 | import './NotAlignedNames' 14 | 15 | -------------------------------------------------------------------------------- /generate-examples.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as path from 'path' 3 | import * as M from './src/model' 4 | import * as P from './src/printer' 5 | import * as E from './test/examples' 6 | import { defaultOptions } from './src/ast' 7 | 8 | const examples = Object.keys(E).map(k => (E as any)[k] as M.Data) 9 | 10 | const print = P.print(defaultOptions) 11 | 12 | examples.forEach(example => { 13 | const code = print(example) + '\n\n' 14 | const filePath = path.join(__dirname, `./examples/${example.name}.ts`) 15 | fs.writeFileSync(filePath, code, { encoding: 'utf-8' }) 16 | }) 17 | 18 | const index = examples.map(example => `import './${example.name}'`).join('\n') + '\n\n' 19 | 20 | fs.writeFileSync(path.join(__dirname, `./examples/index.ts`), index, { encoding: 'utf-8' }) 21 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | collectCoverage: true, 5 | collectCoverageFrom: ['src/**/*.ts'], 6 | transform: { 7 | '^.+\\.tsx?$': 'ts-jest' 8 | }, 9 | testRegex: 'test', 10 | moduleFileExtensions: ['ts', 'js'], 11 | coverageThreshold: { 12 | global: { 13 | branches: 100, 14 | functions: 100, 15 | lines: 100, 16 | statements: 100 17 | } 18 | }, 19 | modulePathIgnorePatterns: ['examples.ts', 'helpers.ts'] 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fp-ts-codegen", 3 | "version": "0.4.0", 4 | "description": "TypeScript code generation from a haskell-like syntax for ADT", 5 | "files": [ 6 | "lib" 7 | ], 8 | "main": "lib/index.js", 9 | "typings": "lib/index.d.ts", 10 | "scripts": { 11 | "lint": "tslint -p tsconfig.json src/**/*.ts test/**/*.ts", 12 | "jest": "jest", 13 | "prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"", 14 | "fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test}/**/*.ts\"", 15 | "test": "npm run prettier && npm run jest && npm run docs && npm run examples && npm run playground", 16 | "clean": "rimraf rm -rf lib/*", 17 | "build": "npm run clean && tsc", 18 | "dtslint": "dtslint dtslint", 19 | "mocha": "mocha -r ts-node/register \"./test/**/*.ts\" --recursive", 20 | "examples": "rimraf examples/*.ts && ts-node generate-examples.ts && ts-node examples/index.ts", 21 | "playground": "webpack --config playground/webpack.config.js", 22 | "watch-playground": "webpack --config playground/webpack.config.js --watch", 23 | "docs": "docs-ts" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/gcanti/fp-ts-codegen.git" 28 | }, 29 | "author": "Giulio Canti ", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/gcanti/fp-ts-codegen/issues" 33 | }, 34 | "homepage": "https://github.com/gcanti/fp-ts-codegen", 35 | "dependencies": { 36 | "fp-ts": "^2.0.1", 37 | "monocle-ts": "^2.0.0", 38 | "parser-ts": "^0.6.0", 39 | "typescript": "^3.5.2" 40 | }, 41 | "devDependencies": { 42 | "@types/jest": "^23.3.13", 43 | "@types/node": "^10.12.18", 44 | "@types/prismjs": "^1.9.0", 45 | "@types/react": "^16.7.21", 46 | "@types/react-dom": "^16.0.11", 47 | "docs-ts": "^0.1.0", 48 | "dtslint": "^0.4.2", 49 | "jest": "^24.8.0", 50 | "mocha": "^5.2.0", 51 | "prettier": "^1.16.4", 52 | "prismjs": "^1.15.0", 53 | "react": "^16.7.0", 54 | "react-dom": "^16.7.0", 55 | "react-simple-code-editor": "^0.8.0", 56 | "rimraf": "^2.6.3", 57 | "ts-jest": "^24.0.2", 58 | "ts-loader": "^5.3.3", 59 | "ts-node": "3.3.0", 60 | "tslint": "^5.12.1", 61 | "tslint-config-standard": "^8.0.1", 62 | "webpack": "^4.29.0", 63 | "webpack-cli": "^3.2.1" 64 | }, 65 | "tags": [ 66 | "fp-ts", 67 | "ADT" 68 | ], 69 | "keywords": [ 70 | "fp-ts", 71 | "ADT" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /playground/index.tsx: -------------------------------------------------------------------------------- 1 | import * as E from 'fp-ts/lib/Either' 2 | import { pipe } from 'fp-ts/lib/pipeable' 3 | import { highlight, languages } from 'prismjs' 4 | import 'prismjs/components/prism-typescript' 5 | import * as React from 'react' 6 | import * as ReactDOM from 'react-dom' 7 | import Editor from 'react-simple-code-editor' 8 | import * as pkg from '../package.json' 9 | import { run } from '../src' 10 | import { defaultOptions, lenses, Options } from '../src/ast' 11 | 12 | const defaultSource = 'data Option A = None | Some A' 13 | 14 | interface Props { 15 | source: string 16 | handlersStyle: Options['handlersStyle'] 17 | } 18 | 19 | interface State extends Props { 20 | code: string 21 | } 22 | 23 | const getState = (source: string, handlersStyle: Options['handlersStyle']): State => { 24 | const options = lenses.handlersStyle.set(handlersStyle)(defaultOptions) 25 | return { 26 | source, 27 | handlersStyle, 28 | code: pipe( 29 | run(source, options), 30 | E.getOrElse(e => `/*\n${e}\n*/`) 31 | ) 32 | } 33 | } 34 | 35 | class App extends React.Component { 36 | constructor(props: Props) { 37 | super(props) 38 | this.state = getState(props.source, props.handlersStyle) 39 | } 40 | 41 | render() { 42 | const onValueChange = (code: string) => { 43 | console.log(code) 44 | } 45 | const onCodeChange = (e: React.ChangeEvent) => { 46 | this.setState(getState(e.currentTarget.value, this.state.handlersStyle)) 47 | } 48 | const onHandlersStyleChange = (e: React.ChangeEvent) => { 49 | if (e.currentTarget.checked) { 50 | this.setState(getState(this.state.source, { type: 'record', handlersName: 'handlers' })) 51 | } else { 52 | this.setState(getState(this.state.source, { type: 'positional' })) 53 | } 54 | } 55 | const onExampleChange = (e: React.ChangeEvent) => { 56 | this.setState(getState(e.currentTarget.value, this.state.handlersStyle)) 57 | } 58 | return ( 59 |
60 |

61 | {pkg.name} playground (v{pkg.version}) 62 |

63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
SourceOutput (unformatted)
73 |