Hacker News new | ask | show | jobs
by dschiptsov 4607 days ago
This is solved long ago, without taking any extremes. In short, a language should be mostly-functional, which means when you really need to overwrite a value you just do it. In well-researched languages, such as Scheme you have set!, in CLs you have setf.

All the monadic stuff (remember, that a monad is nothing but an ADT - Abstract Data Type) is already an extreme, because one must structure the code in a certain way. However, one could write monads in Scheme, there is absolutely nothing special about them.

I think that monad madness it is of the same nature as over-engineering madness that plagues OOP - wasting of time and effort on construction of vast, meaningless class hierarchies.

On the other hand, to find a balance is the most difficult task. Scala, it seems, is close enough, but the ugliness of static typing - parametrized types polymorphism is still here. On the other hand, it avoids mutation whenever possible, uses persistent data structures and first class functions, which results in a much more reasonable and predictable, and, as a consequence, reusable and manageable code (modularity with almost no side-effects).

Yet another point is that there are literally tens of implementations of OOP features for CLs and even Schemes, which might suggest to you that OOP is just a set of conventions and rules - how to reference and dispatch methods - nothing but pointers and procedures, which are the most fundamental abstractions in CS.

The big ideas from Lisps, like everything is a reference, values have type (tags) not variables (you don't need Nothing to be a subclass of everything,) together with first-class functions without side-effects is that good-enough set of features for a programming language.

The point is that so-called "best of the both words" was discovered long ago in classic Lisps and it could be loosely called a mostly-functional language.

1 comments

You can't have monads in Scheme due to the lack of a type system. What you can have are instances of monads, but the point of using the concept of a monad is to abstract over it, and to have functions that work with any possible instance.
Functions that work on "any monad" in Scheme can accept the monad operations as an extra parameter. A macro can hide this, like

    (with-monad m
       (monad-operation data))
See https://github.com/clojure/algo.monads for an implementation of this in Clojure.
> You can't have monads in Scheme due to the lack of a type system.

You can have monads in almost any language. The lack of static typing means you don't have static type safety with them, but monads aren't any different than anything else in that regard.

> What you can have are instances of monads, but the point of using the concept of a monad is to abstract over it, and to have functions that work with any possible instance.

How does not having static typing prevent you from abstracting over monads? You can still write functions that work with any possible instance of a monad in languages without static typing.

> How does not having static typing prevent you from abstracting over monads?

They were probably talking about the way Haskell can figure out which monad you're in through type inference. As an example, `return :: a -> m a` dispatches on the type of the function's return value, which doesn't map cleanly to a dynamically typed implementation. You need to be explicit about the monad you're in if you don't have the compiler helping you out.

That's true (and, heck, its true even of many static languages that support monads; that feature of Haskell is due to its better-than-most type inference, not just having static typing), but I don't see how that limits the capacity for abstraction. Certainly, you may need an additional explicit parameter in some cases rather than effectively implicitly supplying information via type inference, but that doesn't change the level of abstraction.
http://www.pvk.ca/Blog/2013/09/19/all-you-need-is-call-slash...

Think again, Paul Khoung walks you through implementing some monads using call/cc

Genuinely wondering: does this provide type safety?
No, that would happily evaluate "(sequence_ ((display 'a) nothing))".