Created
April 18, 2019 21:58
-
-
Save fvilante/2639be00035a938d50a7d27915b7ed59 to your computer and use it in GitHub Desktop.
An example of Functor in TypeScript. You can run this on https://www.typescriptlang.org/play/
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
// ============================================== | |
// PROPOSAL OF SOLUTION | |
// ============================================== | |
// ================================ | |
// Emulate nominal type-system | |
// ================================ | |
type Kind<K> = { kind: K } | |
type Value<T> = { value: T } | |
type Container<K, T> = Kind<K> & Value<T> | |
type Unit<K> = <T>(value: T) => Container<K, T> | |
const Unit = | |
<K extends string>(kind: K):Unit<K> => <T>(value: T) => | |
({kind, value}) | |
// ================================ | |
// The map (aka: Functor) | |
// ================================ | |
// curied version | |
const map_ = | |
<KB extends string>(unit: Unit<KB>) => | |
<A, B>(fn: (_: A) => B) => | |
<KA extends string>(m: Container<KA, A>): Container<KB, B> => | |
unit(fn(m.value)) | |
// uncuried version | |
const map = | |
<KB extends string, KA extends string, A, B> | |
(unit: Unit<KB>, | |
fn: (_: A) => B, | |
m: Container<KA, A>): Container<KB, B> => | |
unit(fn(m.value)) | |
// ================================ | |
// Use | |
// ================================ | |
// Box now is a polimorphic nominal type constructor | |
const Box = Unit("Box") | |
const OtherBox = Unit("OtherBox") | |
// example | |
const boxedString = Box("hello world") | |
const boxedNumber = Box(10) | |
// Functor map can't fail now | |
const mapbox = map(Box, (x:number) => x * 2, Box(3)) | |
const mapOtherBox = map(OtherBox, (x:number) => x * 2, Box(3)) | |
// You can use partially aplied version | |
const mapBox_ = map_(Box) | |
const mapOtherBox_ = map_(OtherBox) | |
// Use of curried version | |
const mapped = mapBox_((x:string) => x + "world")(Box("hello")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment