Dear all,

** Note that this question is not for practical programming, but just play
for fun.**

I want to implement Maybe monad in Racket.

The following code works.

```
(struct Just (a)
  #:transparent)
(struct Nothing ()
  #:transparent)

(define (bigger-than-two n)
    (if (> n 2)
        (Just n)
        (Nothing)))

(define (>>= mx f)
  (match mx
    [(Nothing) (Nothing)]
    [(Just x) (f x)]))


(>>= (bigger-than-two 4)
      (λ (x)
        (>>= (bigger-than-two 5)
              (λ (y)
                (Just (+ x y))))))
```

The disadvantage of this implementation is that it doesn't look nice.

So I want to implement do notation.

One way to implement do notation is by using Lisp macro, but I don't want
to use macro.

There is an alternative of Lisp macros called FEXPRs, see
https://en.wikipedia.org/wiki/Macro_(computer_science)#Early_Lisp_macros

> Early Lisp macros
> Before Lisp had macros, it had so-called FEXPRs, function-like operators
whose inputs were not the values computed by the arguments but rather the
syntactic forms of the arguments, and whose output were values to be used
in the computation. In other words, FEXPRs were implemented at the same
level as EVAL, and provided a window into the meta-evaluation layer. This
was generally found to be a difficult model to reason about effectively.

More information, see https://en.wikipedia.org/wiki/Fexpr

Therefore, I attempt to use fexpr to simulate macro.

The following code simulates fexpr by `eval` to implement Maybe monad.

```
(struct Just (a)
  #:transparent)
(struct Nothing ()
  #:transparent)

(define (bigger-than-two n)
    (if (> n 2)
        (Just n)
        (Nothing)))

(define (do env binds return)
  (match binds
    [nil
     (eval return env)]
    [`((,var ,e) ,rest-binds)
     (match (eval (e env))
       [(Nothing) (Nothing)]
       [(Just x) (do (extends-env env var x) rest-binds return)])]))

(do (get-current-env)
    (list '[x (bigger-than-two 4)]
          '[y (bigger-than-two 5)])
  '(Just (+ x y)))
```

Unfortunately, this code doesn't work, because it lacks two functions,
`get-current-env` and `extends-env`.

Is there any way to work around this issue?

I have searched Racket's document. Racket has namespaces that are very
similar to the environment here.

But it seems that `current-namespace` can not get binding (e.g. Just) and
`namespace-set-variable-value!` is a mutable function which is not suitable
as well.

Could someone give me some advice?
Or we can modify the code above to make it work in Racket.

Very thanks.

Best regards,
Siyuan Chen

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAHWTsYnhHCwg1gQuZVG%2BjnwLmnC3_8UK4L4n98JpTJ9PWePKxg%40mail.gmail.com.

Reply via email to