@screwlisp computing numbers that are not in the set of {integers modulo 2^64} is really difficult. I have always appreciated how Common Lisp and Scheme both show a great deal of respect to the field of numerical computation by providing programmers with a proper numerical tower.
Re. monads: a struct is a part of a monad, the other part is the binding function that unfreezes the thunk and binds it’s result to an argument of the next thunk. I think the let* binding is a good example of the Identity monad, which is a trivial monad that does nothing but bind variables. You understand how the let* binding can be macro expanded to lambdas, right?
(let*((a (f1 "hello"))
(b (f2 "world")))
(concat a b))
…can be written as…
(funcall
(lambda (a)
(funcall
(lambda (b) (concat a b))
(f2 "world")))
(f1 "hello"))
This is an example of how funcall performs the bind operation of the monad. You can introduce a struct or a record type to chain the lambda functions together and evaluate the monad using a function that runs funcall but also performs some other action before it binds the result of the funcall to the next lambda in the chain. Then if you write a macro like monadic-do where you can build up your chain of lambdas in your record types, it looks like an ordinary procedure but with different semantics than ordinary let*. This is essentially what a monad is.
(monadic-do 'my-stateful-funcall
(a := f1 "hello")
(b := t2 "world")
(concat a b))
Monads are useful to Haskell because this allows you to express procedures using only the minimal semantics of System-F that Haskell provides to you, and can do so in a way that the type system can absolutely prove to be correct.
But I don’t see much use for monads in Common Lisp or Scheme because these languages already provide you with procedures, macros, and other means of changing the semantics of your procedures.