archives

Monads vs. Actors

I just read Gilad Bracha's post "Why Monads Might not Matter." He argues that monads are probably too complicated for most programmers to understand, and that actors might work better as a primary abstraction to solve similar problems. Sharing a similar school of OO thought, this post really resonates with me, although I wonder if we are still misunderstanding monads. In particular, are monads meant to be...

  1. Primary programmer abstractions for interfacing with all things stateful with grand composability benefits from such uniformity.
  2. Abstractions for language/library designers to build programmer abstractions that hide their monadic heritage, perhaps to be revealed only to other language designers who are building other composable abstractions.
  3. Beautiful/elegant abstractions for describing how state is manipulated in a pure functional programming language, but not necessary or practical when an impure language is being used.

Glancing at the comments, I see many arguments. Monads have supposedly been successfully used in scalaz, but I wonder if this is because Scala has attracted more Haskell programmers than Java programmers as of late. Monads and more general arrows have been used to describe FRP, but I always thought that this was an implementation detail that distracted from elegance of the FRP abstractions themselves (and as a result I really didn't get FRP until making the connection with FrTime). Erik Meijer et al. have brought monad-based technology to .NET via yield statements, LINQ, and Rx, but again...when using these abstractions, I don't see or care about whatever monads are involved. Am I still missing the point?

Surely actors can be implemented with monads, but that isn't the point. What should programmers see?

Ela, dynamic functional language

Hi,
I just wanted to share some information about the language I am currently working on.

The language is called Ela. It lives here.

Ela is an impure functional language with dynamic typing. Its syntax is heavily inspired by MLs/Haskell. Ela is strict by default but does support non-strict evaluation as well. Some features:

  • Curried functions
    Nothing new here:

    //"cout" is a console output function; "$" is a sequencing operator like ";" in C
    let out x = cout x $ out 
    
    out "One" "Two" "Three" "Four"
    
  • Function definition by pattern matching
    The known map function in Ela:

    let map f x::xs = f x :: map f xs;
            _ []    = []
    
  • Polymorphic variants
    The idea comes from OCaml but has a pretty different implementation in Ela:
  • let x = `Some 12 //Here we "tag" an integer value with the "Some" tag
    let (`Some y) = x //You can pattern match it
    let res = x + y //You still can treat the tagged value as an integer
    
  • Thunks
    Thunks in Ela are transparent - no need to explicitely call Force function or the like:

    let t = (& 2 + 2)
    let res = t * 2
    
  • Lazy lists
    Lazy lists are constructed using thunks. Here is an example of infinite list filtering:

    let lst = [1,4..]
    
    let filter' p x::xs | p x  = x :: (& filter' p xs);
                        | else = filter' p xs;
                _ []           = []
    
    let nlst = filter' (>10) lst
    
  • Ranges and lists comprehensions
    Can do both eager and lazy lists:

    let lst1 = [1,5..25] //[1,5,9,13,17,21,25]
    
    let lst2 = [1,3..] //infinite list [1,3,5,7..]
    
    let lst3 = [x + y @ (x,y) <- [(1,2)..(4,5)] | x > 2] //[7,9]
    
  • Traits
    Ela type system is based on traits and all operations are abstract. For example you can fold strings like lists (but strings are not lists in Ela) and sum tuples:

    let foldl f z x::xs = foldl f (f z x) xs;
              _ z []    = z
    
    let reverse = foldl (flip (::)) []
    
    let revStr = reverse "Hello, world!"
    
    let res = (1, 2) + (3, 4) //equals to (4, 6)
    
  • First class modules
    Modules are first class values in Ela:

    open Math
    open SymbolMath
    
    let doSum x y mod = mod.sum x y
    
    let res1 = Math <| doSum 2 2
    
    let res2 = SymbolicMath <| doSum 2 2
    

Ela is implemented in 100% .NET/C# and supports Mono. Currently it uses its own backend - stack based virtual machine.

There is some documentation available for those who want to know more. And there are binary releases (no installation required).

There is also an online interactive console available here. It supports all the language features except of an ability to use external modules.

I am opened to critics, questions, suggestions :)

Thanks.