Hacker News new | ask | show | jobs
by eru 629 days ago
Thanks for the context! It's been a while since I did serious work in the Lisps. (I've moved on to the ML family.)

> [...] GNU/MIT Scheme is what you want to follow along with MIT publications working in Scheme (like Structure and Interpretation of Computer Programs, Structure and Interpretation of Classical Mechanics, and The Art of the Propagator).

Definitely, though I suspect if you need a language that's exactly what's written in the text, you are probably missing the point? At least for SICP, I haven't looked into the others as closely. (Part of) the point being learning wider concepts.

I almost feel like you get more out of the book, if you do the exercises in a mix of JavaScript and Python. Not because those are better languages, just the opposite: because it forces you to understand the concepts well enough to translate them.

1 comments

In SICM they frequently make use of a kind of implicit applicative lifting (I can't remember what they call it) where you apply a vector-of-functions as if it were a function itself. In psuedo-Haskell:

    lift :: Vec (a->b) -> (a->Vec b)
    lift [] a = []
    lift f:fs = (f a):(lift fs $ a)
so that you can write natural-looking multidimensional physics expressions like

    ((fx fy fz) r)
without having to invoke macros or restructure the expression to please the compiler. I dearly wish you could do this in another scheme but so far I haven't found one. Iirc it's required for using the magnificent `scmutils` package too.

For example, `guile-scmutils`[0] says:

> Functionality not available in the port:

> Scheme extension to allow applying vectors/structures as procedures. For example rather than

    1 ]=> (pe ((up (literal-function 'x) (literal-function 'y)) 't))
    (up (x t) (y t))
> you must use

    guile> (pe ((lambda (t) (up ((literal-function 'x) t) ((literal-function 'y) t))) 't))
    (up (x t) (y t))
[0] https://www.cs.rochester.edu/~gildea/guile-scmutils/
Clojure has a really nice `juxt` function for that, which I have an implementation of in my `.guile` file.

  (define (juxt . fns)
    (lambda args
      (map (lambda (fn) (apply fn args)) fns)))
lift = sequenceA @[] @(a ->)
Did you do that by hand? I guessed you used the classic `pointfree` program, bit that gave

    lift = fix ((`ap` tail) . (. head) . flip ((.) . liftM2 (:)))
As far as I know it's not possible to get this functionality in Haskell even with clever instance magic, but I'd love to be proved wrong.
> As far as I know it's not possible to get this functionality in Haskell even with clever instance magic

It is possible to fill in basic function bodies based on their type, using ghc-justdoit (https://hackage.haskell.org/package/ghc-justdoit). That's maybe not what you meant, if you are looking for integrating pointfree into Haskell it can be added to ghci or your development environment.

    foo :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r)
    foo = (…)
In this case I wrote it because I knew about the pattern. Your lift definition is just ($)

      flip \a -> ($ a)
    = flip (&)
    = flip (flip ($))
    = ($)
Maybe you meant to write

    (??) :: Functor f => f (a -> b) -> a -> f b
    funs ?? a = fmap ($ a) funs
from lens: https://hackage.haskell.org/package/lens-5.3.2/docs/Control-...

This is valid definition of lift along a different, less interesting but more general axis.

    lift = (??) @[]

    lift = flip $ \a -> ($a)