chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] [ANN] Monad Egg


From: Jörg F . Wittenberger
Subject: Re: [Chicken-users] [ANN] Monad Egg
Date: 15 Apr 2012 20:08:05 +0200

On Apr 15 2012, Daniel Leslie wrote:

Hmm...

I'm not an expert, but I'll try to explain how I see things and maybe it
will make sense.

Neither am I an expert at all.

Especially since I'm struggling to relate the Haskell style
signature notation to my personal lambda/values way of
understanding.

Here's how it works now:

(using <id>
 (>>= (>>= (return 1)
             (lambda (x) (+ x 1))))
         (lambda (y) (+ y 2))))

I did not even come as far as considering the syntax provided
by the egg.  Sorry.

I think I got that right... Basically, the order of operations becomes
inverted when you begin combining binding functions. You end up with the
logically last function to be applied appearing at the top of the binding
chain.

BTW: here I follow by means of abstract logic.

However the logger monad is a good example to explain my point.
Maybe this makes sense.

I'll add some comments:

(define-monad <logger>
(lambda (a) (let ((p (car a))
         (v (cdr a)))
     (fprintf p "Starting with: ~S\n" v)
     a))
 (lambda (a f)
   (let* ((p (car a))
          (v (cdr a))
          (r (f v)))
     (fprintf p "Calling (~S ~S) returned ~S\n" f v r)

;; This is the case I meant when asking for multiple values
;; to be passed as the "monad state".  Ignoring possible
;; implementation related issues, this "cons" is not here
;; to create a pair, but to pass two values where the API
;; has only one slot.
;;
;; Here I'd like to be able to subsitute "(values p r)".

     (cons p r))))

(define (f1 x) (+ x 1))
(define (f2 x) (- x 1))

(define m
 (doto-using <logger>
;; Logically this would then become a
;; "(values (current-output-port) 0)
(cons (current-output-port) 0) f1 f2))

At that point we need to consider how the "monad state"
would be passed back in:

(define-monad <logger>
(lambda (a) (let ((p (car a))
         (v (cdr a)))
     (fprintf p "Starting with: ~S\n" v)
     a))
 (lambda (a f)

!! Here !!

   (let* ((p (car a))
          (v (cdr a))
          (r (f v)))
     (fprintf p "Calling (~S ~S) returned ~S\n" f v r)

With a single "a" as internal state is seems not to matter
much.  Except for the visual elegance of NOT swapping
the "f" and "a" letters within the hopelessly useful
identity monad definition.

However if the implementation was able to pass multiple
values as internal state, I'd prefer to always know the
first argument to be the "f" parameter followed by
N parameters of internal state than the other way around.

Freehanding fictionally rewriting the logger here:

(define-monad <logger>
(lambda (p v) (fprintf p "Starting with: ~S\n" v)
    (values p v)))
 (lambda (f p v)
   (let ((r (f v)))
     (fprintf p "Calling (~S ~S) returned ~S\n" f v r)
     (values p r))))

Does this help?

CU

/Jerry





reply via email to

[Prev in Thread] Current Thread [Next in Thread]