[Nix-dev] [***SPAM***] Re: Use Haskell for Shell Scripting

Michael Raskin 7c6f434c at mail.ru
Wed Feb 11 09:15:42 CET 2015


>>> Oh, Common Lisp (CL) macros don't correspond to TH, but rather to
>>> regular functions in Haskell.  We have first class actions together
>>> with lazy evaluation.  What is "code is data is code" in CL is
>>> "actions are first class values" in Haskell.
>>>
>>> You only need TH when you need to generate something that is not
>>> first class, for example class instances.
>>
>> And many actions are first class values in CL. But there are many
>> things that are not first class even in Haskell. Macros can manipulate
>> lexical environments in many convenient ways, for example.
>>
>> Also, while you could make a function out of a complex iteration
>> macro, it is guaranteed to be simpler to use.
>
>Remember that we're talking about very different paradigms.  I can
>totally see how you would want and love macros in CL.  In CL you encode
>your solution in such a way that using macros is the natural thing to
>do, and then lexical manipulation is probably something that comes in
>handy.  In Haskell your encoding is entirely different, so you wouldn't
>use macros in the first place.  Instead you would use non-strict
>higher-order functions together with type classes.

And of course Common Lisp does have higher-order functions; do type 
classes add any encoding power? I always thought they were needed to 
keep track of all that happens, and working duck typing with optional
multiple dispatch allows to write the same code but with less safety.

There is a myth on the Lisp side that Common Lisp has a paradigm that
means it wouldn't benefit from some more static annotation and analysis
features; there is a myth in many non-Lisp places that feature X makes
macros unneeded.

Both are myths. Just a trivial with-fields (in its many many forms) is
an example of a thing that is trivial with macros, useful enough to be
built into Object Pascal and doesn't perform its primary task (reducing
clutter) if implemented without macros.

>> Ah, so Haskell has no usable records without lenses?
>
>The standard record system is very limited, even though some language
>extensions try to improve it (without much success).  However, you would
>most likely want to use lenses anyway, even if standard records were
>richer.
>
>Modern van Laarhoven lenses are a powerful abstraction for accessing
>data structures, mainly because a lens does not necessarily correspond
>to a certain concrete field (it can correspond to many fields or to a
>logical alternate view of certain data) and also because both lenses and
>lens operators are first class values.

_Which_ lenses should be used, actually? It looks like there is 
a controversy about which packages are the correct ones to use and which
should be considered just a proof-of-concept playground for new ideas.

>Where `temps` is a list of temperatures in degrees Celsius, the
>following is that list with three degrees Fahrenheit added to each item:
>
>    (traverse . fahrenheit +~ 3) temps
>
>The thing in parentheses is a function that takes any traversable data
>structure (e.g. lists or trees), interprets its values as temperatures,
>applies a Fahrenheit view and then adds 3.  The result is the modified
>data structure (i.e. it's pure).
>
>The following is the same function, except that it only adds if the
>original temparature is greater than 10.  All lower temperatures remain
>untouched:
>
>    traverse . filtered (> 10) . fahrenheit +~ 3
>
>Finally as said lenses and lens operators are first class, so you can
>take them as arguments, return them as results and put them into data
>structures.  Let `fields` be a list of lenses.  Then the following is a
>list of lenses pointing deeper into the individual data structures (into
>the `field` subfield of whatever each lens points to):
>
>    (traverse %~ (. field)) fields
>
>That's why we love lenses.  They are more than just a recovery from our
>lack of a decent record system.  And they are defined in plain Haskell,
>just to show you how far we can go without macros. =)

Well, you haven't yet impressed me. I knew Haskell optimiser beats SBCL
at some tasks; just writing all this functionality without macros is 
also straightforward in Common Lisp or Racket or whatever, but inlining
would probably be suboptimal in some cases so macros (mabe just compiler
macros) would be a good optimisation technique to use in Lisp for such
a task.

Types offer safety and also documentation that cannot get out of date;
for pure encoding power I guess you need to find a more complex example.

Of course, macros are useful for mutation. Macros are useful for lexical
environment mutation. They also allow to define custom sugar. Also
macros allow to do some debugging operations like quickly adding very 
verbose logging for later grepping. 

Some blog post about Haskell not needing macros explained how to replace
various macro uses with various Haskell extensions; some of them were
already in development in GHC but not released. With macros
experimenting with such extensions becomes way cheaper; on the bright
side whoever needs that, can do it right away, on the dark side the
features may end up implemented in a few competing ways and never get
unified.





More information about the nix-dev mailing list