[Haskell-beginners] Designing complex Haskell programs

Courtney Robinson courtney at crlog.info
Sun Jan 5 16:43:25 UTC 2014


Okay, thanks. I'll do that.


On Sun, Jan 5, 2014 at 10:56 AM, Bob Ippolito <bob at redivi.com> wrote:

> Okay, for that kind of usage I think an MVar or something like it is your
> best bet, since it really does sound like global state:
>
> startServer :: NodeSettings -> IO ()
> startServer conf = do
>   print "Bootstrapping, trying to reach configured seed nodes"
>    clusterVar <- newMVar . G.bootstrapNode $ seedNodes conf
>   print "Initializing Gossip"
>   gossip clusterVar conf
>   print "Listening for client connections"
>   listenForClients clusterVar conf
>   print "Server shutting down..."
>
> In the clients when you need to read the latest state of the cluster, you
> would use:
>
>   cluster <- readMVar clusterVar
>
> To update the state, you might have something like this:
>
>   modifyMVar_ clusterVar (\_oldCluster -> return newCluster)
>
>
>
>
> On Sun, Jan 5, 2014 at 12:42 AM, Courtney Robinson <courtney at crlog.info>wrote:
>
>> Didn't see your response, my gmail auto filter marks my haskell messages
>> as read and puts them in a folder so I have to explicitly check to see.
>> Anyway:
>>
>> The bit of code I'm stuck on is:
>> startServer :: NodeSettings -> IO ()
>> startServer conf = do
>>   print "Bootstrapping, trying to reach configured seed nodes"
>>   let cluster = G.bootstrapNode $ seedNodes conf
>>   print "Initializing Gossip"
>>   gossip cluster conf
>>   print "Listening for client connections"
>>   listenForClients cluster conf
>>   print "Server shutting down..."
>>
>> The recursive version I had that was similar to yours has long since gone
>> because I couldn't get it to work.
>> bootstrapNode returns [RemoteNode].
>> So at the moment the cluster info is fetched once and that's it, where it
>> falls apart in my head is when I try to change this so that cluster is
>> updated every n seconds.
>>
>> listenForClients is on the main thread with each accepted connection run
>> with forkIO.
>>
>> All I came up with was after "gossip conf" , I could do
>> forkIO someFn where
>>
>> someFn = do
>>  threadDelay n
>>  let cluster = G.bootstrapNode $ seedNodes conf
>>
>> but obviously this doesn't work because my "gossip"  and
>> "listenForClients" functions already have an immutable version of cluster.
>> So I'm not sure how to get the updated version to those fns.
>>
>> Bare in mind that listenForClients and gossip are doing something similar
>> to
>>
>>   withSocketsDo $ do
>>   sock <- listenOn $ PortNumber(fromInteger gossipPort)
>>
>> so only accepting a new connection causes those threads to do anything,
>> but when a connection is accepted, if the request demands the cluster data
>> those fns shouldn't go off gathering the data and shouldn't send the
>> (probably) out dated one from the initialization but instead the one that's
>> been updated every n in the background.
>>
>> Thanks
>>
>>
>> On Fri, Jan 3, 2014 at 6:17 PM, Bob Ippolito <bob at redivi.com> wrote:
>>
>>> I wouldn't recommend going down the path of using IORef or MVar for
>>> everything, it's not easy to build robust systems that way. Do you mind
>>> showing the code that you tried that "fell apart"? I'm sure there's a
>>> slightly different way to structure it that would work just fine, probably
>>> using some kind of message passing.
>>>
>>>
>>> On Fri, Jan 3, 2014 at 9:57 AM, Courtney Robinson <courtney at crlog.info>wrote:
>>>
>>>> Thanks to both of you for your reply.
>>>> I have something similar to your example Bob, wasn't sure if it was a
>>>> good way forward. Plus it fell apart when I tried contacting multiple hosts
>>>> on different threads using forkIO. But with Daniel's response I'll look
>>>> into MVars.
>>>>
>>>> Thanks again
>>>>
>>>>
>>>> On Fri, Jan 3, 2014 at 5:16 PM, Bob Ippolito <bob at redivi.com> wrote:
>>>>
>>>>> Generally speaking, state lives on the call stack in functional
>>>>> programming languages that have tail call elimination. Modification of the
>>>>> state is done by recursion with a new value for the state. This is more or
>>>>> less equivalent to a "do while" loop in imperative programming.
>>>>>
>>>>> myServer :: State -> IO ()
>>>>> myServer state = do
>>>>>   state' <- updateState state
>>>>>   myServer state'
>>>>>
>>>>> For the concurrency, Control.Concurrent or Cloud Haskell (for a higher
>>>>> level Erlang-like approach) is probably the way to go here. Parallel and
>>>>> Concurrent Programming in Haskell is a great resource:
>>>>> http://chimera.labs.oreilly.com/books/1230000000929
>>>>>
>>>>>
>>>>> On Fri, Jan 3, 2014 at 8:45 AM, Courtney Robinson <courtney at crlog.info
>>>>> > wrote:
>>>>>
>>>>>> I'm trying to take the training wheels of and moving more of my code
>>>>>> base to Haskell from C++ but finding it increasingly tricky.
>>>>>>
>>>>>> I have a subset of a gossip protocol written in C++.
>>>>>> When a server comes online it connects to 1 or more nodes already in
>>>>>> the cluster and get data from them about other nodes they know of.
>>>>>>
>>>>>> The new node merges the information and keeps a copy of the merged
>>>>>> view. Every so often it contacts the nodes it knows about and refreshes the
>>>>>> merged view. It also must have the up to date view ready to be sent in
>>>>>> response to a new node joining.
>>>>>>
>>>>>> I currently can't wrap my head around how to maintain this state. How
>>>>>> would a more experienced Haskeller approach this problem? Code is OK if it
>>>>>> demonstrates a particular point but I'm more interested in the line of
>>>>>> thought that would go into designing a solution as I suspect that'll be
>>>>>> more useful as I get further into the migration.
>>>>>>
>>>>>> As a gauge to you for my current level in Haskell. I read and
>>>>>> understand most Haskell programs fine. I write some but currently heavily
>>>>>> rely on hackage/hoogle docs for APIs, even some common ones.
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> _______________________________________________
>>>>>> Beginners mailing list
>>>>>> Beginners at haskell.org
>>>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>>>
>>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Beginners mailing list
>>>>> Beginners at haskell.org
>>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Courtney Robinson
>>>> courtney at crlog.info
>>>> http://crlog.info
>>>> 07535691628 (No private #s)
>>>>
>>>> _______________________________________________
>>>> Beginners mailing list
>>>> Beginners at haskell.org
>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>
>>>>
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://www.haskell.org/mailman/listinfo/beginn<http://www.haskell.org/mailman/listinfo/beginners>
>>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
>


-- 
Courtney Robinson
courtney at crlog.info
http://crlog.info
07535691628 (No private #s)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20140105/bf51f356/attachment.html>


More information about the Beginners mailing list