
Show HN: A Haskell library for web and distributed composable applications - agocorona
https://github.com/agocorona/transient-universe
======
brudgers
If it meets the guidelines, this might make a good "Show HN".

Guidelines:
[https://news.ycombinator.com/showhn.html](https://news.ycombinator.com/showhn.html)

~~~
agocorona
I think that it meets the guidelines. It is a matter of reposting it with the
prefix "Show HN"?

~~~
brudgers
Maybe. Or use the contact link to ask the moderator, dang.

------
agocorona
Since JavaScript and the browser is the only thing that matters nowadays:

transient-universe can run Browser nodes compiled from haskell to Javascript.
they can display DOM widgets and are integrated with server nodes, using
websockets communications. Just compile the program with the Haskelll to JS
compiler and point the browser to [http://server:port](http://server:port).
The server nodes have a HTTP server that will send the compiled program to the
browser.

------
throweway
How does it compare with an actor model?

~~~
agocorona
Good question. The actor model communicate via mailboxes, which execute
callbacks sort to say. Essentially this produces the callback hell.

Taking away the initializations, this is the ping pong example in Erlang:

[https://gist.github.com/torgeir/3978785](https://gist.github.com/torgeir/3978785)

    
    
        ping(Receiver) ->
          { pong, Receiver } ! { ping, self() },
          receive
            pong -> io:format("Got pong!~n")
        end.
    
        pong() ->
          receive
    
            finished ->
              io:format("Pong finished~n");
    
            { ping, Sender } ->
              io:format("Got ping!~n"),
              Sender ! pong,
              pong()
          end.
    
    
    

This is the same in Transient: A message is sent to the receiver print "ping"
in his console, then send a message to the sender, that print "pong" in his
console

    
    
        pingPong receiver=  
          wormhole receiver $ do
              teleport
              lliftIO $ print "ping"
              teleport
              lliftIO $ print "pong"
    

You see that the ping and the pong are composed "monadically" in a single
piece of code. The flow is quite understandable.

Just start the program in both nodes (initialization code is not shown)

This is a distributed program but I can compose this program with any other.

This other program stream integers from a remote node from 1 in increasing
order:

    
    
        streamFrom node= 
           wormhole  node $ do
                      teleport
                      r <- threads 1 $ choose[1..]
                      threadDelay 1000000
                      teleport
                      return r
    

I can compose both distributed programs:

    
    
        composed node =  do
             r <-  (pingPong node >> return 0) <|>  streamFrom node
             lliftIO $ case r of
                  0 -> putStrLn "pong was received"
                  n -> print n
    

`composed` print the numbers received and the "pong" messages followed by
"pong was received" in the console of the caller.

------
crb002
How does this compare to Haxl?

~~~
agocorona
Haxl is a great Haskell library and probably the biggest contribution to
getting Haskell out of the academia. It is optimized for fetching querying and
caching data sources, among other things, making use of parallelism and
concurrency while maintaining a level close to the domain problem.

Haxl uses a controlling thread that spawn worker threads and is single
purpose. No distributed computing in the strong sense.

transient has no controlling thread. It run multiple threads and is general
purpose.

The alternative operator <|> can spawn parallel threads/or parallel
distributed computations that follow the flow of the monad. for example:

    
    
        r <-   runAt node1 foo <|>  runAt node2 bar
        lliftIO $ print r
    

will print two results, since there are two thread generated. Well there may
be any number of results because any of the two branches may generate multiple
threads or none, since they can stop without any result.

(if we need a single thread, we can use `collect`)

note that `foo` and `bar` are distributed programs as well, so they can invoke
other nodes and so on.

