Last active
June 16, 2021 20:05
-
-
Save ryyppy/179a90486365e2439cd4e68057e3e0bd to your computer and use it in GitHub Desktop.
deep-dive-reason-union-types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Mark = { | |
[@unboxed] | |
type t = | |
| Any('a): t; | |
module Link = { | |
type attrs = { | |
href: string, | |
target: string, | |
}; | |
type t = {attrs}; | |
}; | |
type case = | |
| Link(Link.t) | |
| Italic | |
| Bold | |
| Unknown(t); | |
let getType: t => string = [%raw | |
{| | |
function(value) { | |
if(typeof value === "object" && value.type != null) { | |
return value.type; | |
} | |
return "unknown"; | |
} | |
|} | |
]; | |
let classify = (v: t): case => { | |
switch (v->getType) { | |
| "italic" => Italic | |
| "bold" => Bold | |
| "link" => Link(v->Obj.magic) | |
| "unknown" | |
| _ => Unknown(v) | |
}; | |
}; | |
}; | |
module Image = { | |
type attrs = { | |
alt: string, | |
src: string, | |
title: option(string), | |
}; | |
type t = {attrs}; | |
}; | |
module Text = { | |
type t = { | |
text: string, | |
marks: option(array(Mark.t)), | |
}; | |
}; | |
[@unboxed] | |
type t = | |
| Any('a): t; | |
module Heading = { | |
type attrs = {level: int}; | |
type h = { | |
attrs, | |
content: array(t), | |
}; | |
}; | |
type case = | |
| Doc(array(t)) | |
| Text(Text.t) | |
| Paragraph(array(t)) | |
| BulletList(array(t)) | |
| OrderedList(array(t)) | |
| ListItem(array(t)) | |
| Unknown(t); | |
let getType: t => string = [%raw | |
{| | |
function(value) { | |
if(typeof value === "object" && value.type != null) { | |
return value.type; | |
} | |
return "unknown"; | |
} | |
|} | |
]; | |
let getContent: t => array(t) = [%raw | |
{| | |
function(value) { | |
if(typeof value === "object" && value.content != null) { | |
return value.content; | |
} | |
return []; | |
} | |
|} | |
]; | |
let classify = (v: t): case => | |
switch (v->getType) { | |
| "doc" => Doc(v->getContent) | |
| "bullet_list" => BulletList(v->getContent) | |
| "ordered_list" => OrderedList(v->getContent) | |
| "list_item" => ListItem(v->getContent) | |
| "text" => Text(v->Obj.magic) | |
| "paragraph" => Paragraph(v->getContent) | |
| "unknown" | |
| _ => Unknown(v) | |
}; | |
// Final Example (should not be part of the actual module) | |
let v = | |
Any({ | |
"type": "text", | |
"text": "Hello World", | |
"marks": [| | |
{"type": "bold"}, | |
{"type": "italic"}, | |
{ | |
"type": "link", | |
"attrs": { | |
"href": "https://reasonml.org", | |
}, | |
}->Obj.magic, | |
|], | |
}); | |
let result = | |
switch (v->classify) { | |
| Text({marks: Some(marks)}) => | |
open! Mark; | |
let r = | |
Belt.Array.map(marks, m => | |
switch (m->classify) { | |
| Bold => "bold" | |
| Italic => "italic" | |
| Link({Link.attrs: {href}}) => "link-href: " ++ href | |
| Unknown(_) => "" | |
} | |
) | |
->Js.Array2.joinWith(", "); | |
"All Marks: " ++ r; | |
| Text({marks: None}) => "No marks found" | |
| _ => "No Text element" | |
}; | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Mark: { | |
type t; | |
module Link: { | |
type attrs = { | |
href: string, | |
target: string, | |
}; | |
type t = {attrs}; | |
}; | |
type case = | |
| Link(Link.t) | |
| Italic | |
| Bold | |
| Unknown(t); | |
let classify: t => case; | |
}; | |
module Text: { | |
type t = { | |
text: string, | |
marks: option(array(Mark.t)), | |
}; | |
}; | |
type t; | |
type case = | |
| Doc(array(t)) | |
| Text(Text.t) | |
| Paragraph(array(t)) | |
| BulletList(array(t)) | |
| OrderedList(array(t)) | |
| ListItem(array(t)) | |
| Unknown(t); | |
let classify: t => case; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment