-
t('конструктор')
нульнарный конструкторt('конструктор', тип)
обычный конструкторt([ t('конструктор'), t('конструктор')] )
перечесление, суммаt.forall(a => t('конструктор', a) )
конструктор принимающий любой типt.recursive(thisType => t('конструктор', thisType) )
конструктор принимающий свой тип
-
const a = t('A') a.A, a.type
создает нульнарный конструктор A и тип
const { B, type } = t('B', t.int) const value = B(10)
создает конструктор B который может хранить тип int
-
const Bool = t([ t('True'), t('False') ]) Bool.True Bool.False Bool.type
haskell
data Bool = True | False
-
t.f = t.forall const { B, type } = t.f( a => t('B', a) ) const valueInt = B(10) const valueStr = B("ABC")
haskell
data B a = B a let valueInt = B 1 let valueStr = B "ABC"
-
t.r = t.recursive const { C, type } = t.r( thisType => t('C', thisType) ) C(C(C( .... )) - бесконечный, так как нет выхода из рекурсии
haskell
data C = C C C ( C ( C ( в бесконечность и далее )))
-
const { Nil, Cons, type } = t.recursive(thisType => t.forall(a => t([ t('Nil'), t('Cons', a, thisType(a)) ]) ) ) const value = Cons( 1, Cons( 2, Nil ) )
haskell
data List a = Nil | Cons a (List a) Cons 1 ( Cons 2 Nil )
reasonml
type list('a) = Nil | Cons('a, list('a)) Cons(1, Cons(2, Nil))
Last active
December 20, 2022 11:36
-
-
Save SergProduction/3cd7d3c28f51fcc10a36acd46642963e to your computer and use it in GitHub Desktop.
This file contains 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
const t = (typeName, ...params) => { | |
if (Array.isArray(typeName)) { | |
function SumType() { | |
typeName.forEach(constr => { | |
this[constr.type] = constr | |
}) | |
this.caseOf = o => compare => { | |
return Object.getOwnPropertySymbols(o).reduce((res, symb) => { | |
if (symb === compare.toString()) { | |
return compare.value.length !== 0 | |
? o[symb](...compare.value) | |
: o[symb] | |
} | |
return res | |
}, null) | |
} | |
} | |
return new SumType() | |
} | |
const uniqName = Symbol() | |
function NullAbelType(...value) { | |
this.toString = () => uniqName | |
this.type = typeName | |
this.value = value | |
} | |
if (params.length > 0) { | |
const productType = (...param) => new NullAbelType(...param.slice(0, params.length)) | |
productType.toString = () => uniqName | |
productType.type = typeName | |
return productType | |
} | |
return new NullAbelType() | |
} | |
const True = t('True') | |
const Bool = t([ | |
True, | |
t('False') | |
]) | |
const unWrap = Bool.caseOf({ | |
[True]: 'True', | |
[Bool.False]: 'False' | |
}) | |
console.log(unWrap(Bool.True)) | |
const Maybe = t([ | |
t('Just', t), | |
t('Nothing') | |
]) | |
const unWrapMaybe = Maybe.caseOf({ | |
[Maybe.Just]: a => 'Just ' + a, | |
[Maybe.Nothing]: 'Nothing' | |
}) | |
console.log(unWrapMaybe(Maybe.Just(5))) | |
fmapMaybe = fn => Maybe.caseOf({ | |
[Maybe.Just]: a => Maybe.Just(fn(a)), | |
[Maybe.Nothing]: Maybe.Nothing | |
}) | |
console.log( | |
unWrapMaybe( | |
fmapMaybe(x => x * 2)(Maybe.Just(9)) | |
) | |
) | |
aplicativeMaybe = (maybeF, maybe) => Maybe.caseOf({ | |
[Maybe.Nothing]: Maybe.Nothing, | |
[Maybe.Just]: (fn) => Maybe.caseOf({ | |
[Maybe.Nothing]: Maybe.Nothing, | |
[Maybe.Just]: a => Maybe.Just(fn(a)), | |
})(maybe), | |
})(maybeF) | |
console.log( | |
unWrapMaybe( | |
aplicativeMaybe(Maybe.Just(x => 1 / x), Maybe.Just(5)) | |
) | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment