Τρίτη 21 Ιουλίου 2020

A Monad Example (OOP)

See this code (written in a module say Alfa). We want a wrapper Maybe class to hold either a monad of type Nothing or a monad of type Integer. Also we define some functions and operators.

Read comments, while follow the class definitions. This example also make lambda composiitons. Operators for groups (group is the M200 user object type) works on groups. So we want here to make two groups to work through an operator which aren't the same type.  We want a group to act as a lambda function, so we have to wrap a lambda function.


\\ the base class for Monad, we make it like Abstract class return an Error if not implemented
Class Monad {
      Operator "+" {
            Error "Abstract"
      }
      Function ToString$ {
            Error "Abstract"
      }
      Function Just {
            Error "Absract"
      }
}
\\ Nothing from base Monad
\\ we don't have a val variable here
Class Nothing as Monad {
      Function ToString$ {
            ="Nothing"
      }
      Operator "+" {
            drop
      }
      \\ we make the set member to use this
      \\ as singleton
      Set {
            drop
            \\ nothing change nothing;
      }
      \\ Always return the global object
      value {
            ->Nothing
      }
      Function Just {
            Error "Nothing"
      }
}
\\ From now on we use monads as pointers
\\ We want to use Nothing as a global variable
\\ of type pointer to group, and a specific Nothing type group
Global Nothing=Pointer(Nothing())
\\ Integer from Monad, wrapping in a lambda to return pointer
mInteger=Lambda ->{
      Class Integer as Monad {
      Private:
            val
      Public:
            Operator "+" (a as monad) {
                  if a is type Nothing then
                        .val<=Nothing
                  Else
                        .val+=a.val
                  End if
            }
            \\ this function return a lambda
            function just {
                   =lambda x=.val -> {
                        =x
                  }
            }
            Function Add(m as *monad) {
                  if m is type Nothing then =m : exit
                  k->(This) ' get a pointer of a copy of this
                  \\ val is private but not in a member of same type
                  \\ and this includes m which is a pointer to a monad
                  k=>val=.val+m=>val
                  =k
            }
            Function ToString$ {
                  =format$("{0}", .Val)
            }
      Class:
            Module Integer (T as Decimal) {
                  .val<=Int(T)
            }
      }
      \\ passing current stack [] to Integer()
      \\ a cascade pass of a parameter list to another function
      \\ so we pass values to constructor of Integer class
      ->Integer(![])
}
\\ Now we make the Maybe Class, with a val as a Null pointer,
\\ but with a constructor which replace the pointer with a Monad pointer
Class Maybe {
Private:
      val=Pointer()
Public:
      \\ this is the Just function on a Maybe
      \\ this return a pointer from a copy of a This.val
      \\ we don't want to export the pointer of .val
      Function Just {
            ->Group(.val)
      }
      \\ export to string using monad's  ToString$()
      Function ToString$ {
            =.val=>ToString$()
      }
      \\ replace the monad inside
      Module Bind (a as *Monad) {
            .val<=a
      }
      \\ get and return a Maybe type
      Operator "+" (a as Maybe) {
            if a.val is type Nothing then
                  .val<=Nothing
            Else
                    \\ Pointer  need ( ) to get the expression
                  .val<=Pointer((.val + a.val))
            End if
      }
      Operator "^*" (f as λ) {
            if not .val is type Nothing then
                  This<=f.x(.val)
            End if
      }
      \\ return a pointer to a Monad
      Function Add(a as Maybe) {
            if .val is type Nothing then
                  =Nothing
            Else
                  =.val=>Add(a.val)
            End if
      }
Class:
      \\ used once, then excluded from final object
      \\ pass parameter list to This.Bind
      module Maybe {
            .Bind
      }
}
Class λ {
}
Class  λ1 as λ {
      \\ remove right to see what happens
      Operator right "^*"  ( f as λ) {
Rem            Print "Inside ^* λ"
            .x<=lambda a=.x, b=f.x -> {
                  \\ each function return a maybe type
Rem                  print "call me"
                  m=b(![])
                  =a(m.just())
            }
      }
      x = lambda ( T as *Integer ) ->{
            T=Pointer((T + T))
Rem            Print "Call Maybe"
            =Maybe(T)
      }
}
\\ K, L and M are static objects for this module
λ=λ1()
K=Maybe(mInteger(100))
M=Maybe(Nothing)
\\ Remove Rem clause from lines above
\\ Then remove clause "right" from λ operator "^*" so this happen:
\\  L=(K ^* λ) ^* λ so we never call operator "^*" in λ
\\ but using "right" from start we do this
\\  L=K ^* (λ ^* λ)  which (λ ^* λ) combine lambda functions
L=K ^* λ ^* λ
Print L.ToString$() '="400"
L=K ^* λ ^* λ ^* λ ^* λ
Print L.ToString$() '="1600"
\\ Lets do the same but now with M which is Nothing
L=M ^* λ ^* λ ^* λ ^* λ
Print L.ToString$() '="Nothing"
Z=Maybe(Nothing)
\\ L is a Maybe class which now binding a Monad of type Nothing
Z.Bind K.Add(L)
\\ so we get nothing
Print Z.ToString$() '="Nothing"
\\ Change binding to L to a Monad of type Integer with value 2000
L.Bind mInteger(2000)
Z.Bind K.Add(L)
Print Z.ToString$() '="2100"
\\ creating M1 to point to a copy of Z's monad
M1=Z.Just()
\\ createing F1 as a lambda function which hold a copy of monads value
If not M1 is type Nothing then F1=M1=>Just()
Print F1()=2100
\\ Now M1 points to a copy of L monad
M1=L.Just()
\\ F1() has a closure (as a copy) of value of Z monad
Print F1()=2100
\\ We can replace F1 (is a lambda) with the current monad which M1
If not M1 is type Nothing then F1=M1=>Just()
Print F1()=2000
\\ lets get M1 from M which has Nothing as Monad
M1=M.Just()
\\ Lets try to execute the M1=>just()
Try Ok {F1=M1=>Just()}
If not Ok Then Print Error$
\\ Lets check if we can add nothing monad with an integer monad
Z=L+M
\\ yes we can do and we get Nothing
Print Z.ToString$() '="Nothing"
\\ yes we can do at reverse order and we get Nothing
Z=M+L
Print Z.ToString$() '="Nothing"
M1=Z.Just()
If not M1 is type Nothing then F1=M1=>Just()
Print F1()=2000

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.