Guest User

Untitled

a guest
Oct 21st, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.63 KB | None | 0 0
  1. // Higher Kind Type dictionary
  2. interface _<A> { }
  3.  
  4. type HKT = keyof _<any>
  5.  
  6. type $<F extends HKT, A> = _<A>[F]
  7.  
  8. // Functor Type Class
  9. interface Functor<F extends HKT> {
  10. map<A, B>(f: (a: A) => B, fa: $<F, A>): $<F, B>
  11. }
  12.  
  13. // Datatype Tag
  14. function datatype(name: string) {
  15. return (constructor: Function) => {
  16. Reflect.defineMetadata('design:type', name, constructor);
  17. }
  18. }
  19.  
  20. function kind(target: any) {
  21. return Reflect.getMetadata('design:type', target.constructor);
  22. }
  23.  
  24. // Xstream Datatype
  25. @datatype('Xstream')
  26. class Xstream<A> {
  27. value: A
  28. constructor(v: A) {
  29. this.value = v
  30. }
  31. }
  32.  
  33. // declare type of Xstream as HKT
  34. interface _<A> {
  35. "Xstream": Xstream<A>
  36. }
  37.  
  38. // declare Functor instance of Xstream
  39. class XstreamFunctor implements Functor<"Xstream"> {
  40. map<A, B>(f: (v: A) => B, fa: Xstream<A>): Xstream<B> {
  41. return new Xstream(f(fa.value))
  42. }
  43. }
  44.  
  45. @datatype('Ystream')
  46. class Ystream<T> {
  47. value: T
  48. constructor(v: T) {
  49. this.value = v
  50. }
  51. }
  52.  
  53. interface _<A> {
  54. "Ystream": Ystream<A>
  55. }
  56.  
  57. class YstreamFunctor implements Functor<"Ystream"> {
  58. map<A, B>(f: (v: A) => B, fa: Ystream<A>): Ystream<B> {
  59. return new Ystream(f(fa.value))
  60. }
  61. }
  62.  
  63. // add instances into Functor dictionary
  64. namespace Functor {
  65. export const Xstream = new XstreamFunctor
  66. export const Ystream = new YstreamFunctor
  67. }
  68.  
  69. type FunctorInstance = keyof typeof Functor
  70.  
  71. // Polymorphic map function
  72. function map<F extends FunctorInstance, A, B>(f: (v: A) => B, fa: $<F, A>): $<F, B> {
  73. return (<any>Functor[fa.constructor.name as F]).map(f, fa) as $<F, B>
  74. }
  75.  
  76. map<"Xstream", number, number>(a => a + 1, new Xstream(1))
  77. map<"Ystream", number, number>(a => a + 1, new Ystream(1))
Add Comment
Please, Sign In to add comment