Side effect tracking in Haskell and D

A readable blog post, and a good Reddit-Programming discussion about the management of side effects in Haskell.

In the Reddit thread there are two answers (first and second) that discuss why Haskell is not so good after all, and suggest possible ways to improve it.

Haskell allows you use the built-in ways to control side-effects, or to design your own ways, with monads. The D language too offers you several ways to control side-effects, but they are more hard-coded (its single-inherintance OOP and struct RAII offer other ways to build your own ways to control effects). There is a strict module system with nested imports too, static/nonstatic nested functions, static/nonstatic nested structs and classes, a modifier to require the access to global names, transitive const/immutable attributes, compile-time constants computed with a kind of staged compilation, transitive const methods for structs and classes, the transitive nothrow attribute to specify function trees that can't raise exceptions, errors, tunable floating point exceptions, the stack memory is thread-local on default plus there are the shared and __gshared attributes, there are protection attributes like protected, public, private both for methods and module-level names, there is both GC-managed memory and C-heap memory, there are the transitive @safe, @system and @trusted attributes that help avoid certain unwanted interactions like memory corruptions, there is the transitive pure attribute that allows to specify strongly-pure or weakly-pure or const-pure functions. At compile-time there are template constraints that use compile-time-function-evaluation too to enforce arbitrary complex properties about template types avoiding unwanted usages too. This is a large amount of built-in ways to control access and side effects. Some D users have proposed other ideas, like linear types, a refined ownership system, @noheap to control heap activity, head-const for reference types, etc.

Language design is a matter of trade-offs. I wonder if in practical programming all such hard-coded things are able to replace part of the flexibility Haskell offers in controlling side effects.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

More than monads

There are quite a few ways you can precisely control effects in Haskell. Monads are among the most flexible - which is often a bad thing. Generalized arrows combined with a capability model and phantom types are likely among the most precise (allowing control over linearity, divergence, precise access to the environment, signal-based constraints on effects, and transform/lift constraints). Other options are functor, applicative and alternative, comonad, the original arrows model, enumerators and iteratees, and so on.

Language design is a matter of trade-offs.

Language design is not a zero sum game. In most cases, you can model your cake and eat it. Figuring out how - without sacrificing symmetry, consistency, or simplicity - is the essence of language design.

I think it a mistake to enter language design with 'trade-offs' in mind! You'll end up engineering a language more than designing one. Of course, engineering can offer objective innovations and improvements. But trade-offs typically cost consistency, symmetry, or simplicity.

D is very much an engineered language. Haskell serves more as a meta-language, but the number of tunable parameters for GHC indicates quite a bit of engineering is involved there, too.