# Write yourself some Haskell for great good..

```; The ideas are quite simple:
; * make a list of actions to perform:
;   (define as (list (delay (display 1)) (delay (display 2)) (delay (display 3))))
; * reduce them one by one, in order, to a value, usually IO ()
;   (force (force (force (sequence_ as))))

; to create a list of promises we need a lazy map from Haskell
(define (lazy-map f xs)
(if (null? xs)
xs
(cons (delay (f (car xs)))
(lazy-map f (cdr xs)))))

; lazy foldr, like in Haskell
(define (lazy-foldr f b xs)
(if (null? xs)
b
(delay (f (car xs)
(lazy-foldr f b (cdr xs))))))

(define (run e)
(and (promise? e)
(run (force e))))

; (>>)           :: Monad m => m a -> m b -> m b
(define (>> a b)                  ; shift
(begin
(force a)
b))

; return         :: Monad m => a -> m a
(define (ret e)                   ; wrap
(delay e))

; some syntactic sugar
(define (do! a b)
(>> a b))

; sequence_       :: [IO ()] -> IO ()
(define (sequence_ as)
(if (null? as)
(ret '())
(do! (car as)
(delay (sequence_ (cdr as))))))

; test
(define as (list (delay (display 1)) (delay (display 2)) (delay (display 3))))
(force (force (force (force (sequence_ as)))))

;sequence_        :: Monad m => [m a] -> m ()
(define (sequence_ as)			; reduce to ()
(lazy-foldr >> (ret '()) as))

; mapM_           :: Monad m => (a -> m b) -> [a] -> m ()
(define (mapM_ f as)
(sequence_ (lazy-map f as)))

; some currying
(define (curry f)
(lambda (x)
(f x)))

; print :: String -> IO ()
(define (print s)
(sequence_ (lazy-map (curry display) s)))

; test
(run (print '(a b c d)))

; test
(run (mapM_ (curry display) '(a b c d)))
```