Skip to content

Instantly share code, notes, and snippets.

@SergProduction
Last active December 20, 2022 11:36
Show Gist options
  • Save SergProduction/3cd7d3c28f51fcc10a36acd46642963e to your computer and use it in GitHub Desktop.
Save SergProduction/3cd7d3c28f51fcc10a36acd46642963e to your computer and use it in GitHub Desktop.
  • t

    • 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

  • сумма/enum/перечислние

    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))
    
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