Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1.  Why does forkIO also create native threads? (Lych)
   2. Re:  Why does forkIO also create native threads?
      (Peter Verswyvelen)
   3. Re:  Re: Thinking about monads (Michael Mossey)
   4.  RWH Ch. 27 TCP Server Example (aditya siram)
   5.  How would you run a monad within another monad? (Arthur Chan)
   6. Re:  How would you run a monad within another     monad?
      (Jason Dusek)


----------------------------------------------------------------------

Message: 1
Date: Mon, 13 Apr 2009 16:37:22 +0800
From: Lych <[email protected]>
Subject: [Haskell-beginners] Why does forkIO also create native
        threads?
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

I wrote a simple ECHO server like this:
----------------------------------------------------
import Network
import System.IO
import Control.Concurrent

service cs = do
        ln <- hGetContents cs
        hPutStr cs ln
        service cs


acceptloop ls = do
     (cs, host, port) <- accept ls
     hSetBuffering cs LineBuffering
     forkIO (service cs)
     acceptloop ls

main = do
     ls <- listenOn (PortNumber 10061)
     acceptloop ls
----------------------------------------------------

And tested it with a client that initiates as many parallel
connections as possible. The number of connections can just reach to
1000+ on my machine, but I thought it should be more, since forkIO
generates lightweight threads. I also examined the number of threads
in this process with some tool and it proved there was one native
thread per connection. When I replaced the 'forkIO' in the program
with 'forkOS', I got an exactly similar result. Have I thought
something wrong about forkIO?


------------------------------

Message: 2
Date: Mon, 13 Apr 2009 20:35:33 +0200
From: Peter Verswyvelen <[email protected]>
Subject: Re: [Haskell-beginners] Why does forkIO also create native
        threads?
To: Lych <[email protected]>
Cc: [email protected], Haskell-cafe Cafe
        <[email protected]>
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"

It seems that it's not the forkIO that is creating native threads (using GHC
6.10.1, -O flag)
For example, the following code only has 5 threads on my Windows box, while
I fork 10 lightweight threads

import System.IO
import Control.Concurrent
import Control.Monad

entry :: Char -> IO()
entry c  = do
  forever $ putChar c
main = do
hSetBuffering stdout NoBuffering
mapM_ (forkIO . entry) ['0'..'9']
putStrLn "all forked; press ENTER to quit"
getLine
However, things can get bizarre. When we change the entry function into

entry :: Char -> IO()
entry c  = do
  putChar c
  threadDelay maxBound

Then on my machine 13 native threads *are* created. This might make sense
because its waiting forever, but native threads are also created for the
following code:

entry :: Char -> IO()
entry c  = do
  putChar c
  forever $ threadDelay 0

This feels like overkill, so it seems threadDelay always forks a new native
thread, although this is not documented.

We can also get into the dark corners of GHC's lightweight thread
scheduling: a thread switch only happens when memory is allocated on the GC
head (but this is documented in the API)

So the following code will not work, the runtime seems to get stuck in an
infinite loop after the first thread is created.

entry :: Char -> IO()
entry c  = do
  putChar c
  forever $ return ()

In artificial cases like this you can use yield

entry :: Char -> IO()
entry c  = do
  putChar c
  forever yield

On Mon, Apr 13, 2009 at 10:37 AM, Lych <[email protected]> wrote:

> I wrote a simple ECHO server like this:
> ----------------------------------------------------
> import Network
> import System.IO
> import Control.Concurrent
>
> service cs = do
>        ln <- hGetContents cs
>        hPutStr cs ln
>        service cs
>
>
> acceptloop ls = do
>     (cs, host, port) <- accept ls
>     hSetBuffering cs LineBuffering
>     forkIO (service cs)
>     acceptloop ls
>
> main = do
>     ls <- listenOn (PortNumber 10061)
>     acceptloop ls
> ----------------------------------------------------
>
> And tested it with a client that initiates as many parallel
> connections as possible. The number of connections can just reach to
> 1000+ on my machine, but I thought it should be more, since forkIO
> generates lightweight threads. I also examined the number of threads
> in this process with some tool and it proved there was one native
> thread per connection. When I replaced the 'forkIO' in the program
> with 'forkOS', I got an exactly similar result. Have I thought
> something wrong about forkIO?
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20090413/12b5b9ba/attachment-0001.htm

------------------------------

Message: 3
Date: Mon, 13 Apr 2009 15:11:42 -0700
From: Michael Mossey <[email protected]>
Subject: Re: [Haskell-beginners] Re: Thinking about monads
To: Ertugrul Soeylemez <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed



Ertugrul Soeylemez wrote:
> Hello Michael,
> 
> you're basically trying to give monads a better name.  Don't forget that
> they are an abstract structure, which means that trying to find
> intuitions or motivations is the same as trying to find real world
> examples.
> 
> Monads are not a way to pass the result of some function to another
> function.  We've got function composition for that.  Short-circuiting is
> a feature of particular monads like Maybe, and as you said, you could
> well do without them.  In Haskell, monads are an abstract combinator
> class, which brings you mainly two advantages:  Generalization of
> functionality and impure operations encapsulated in pure objects.
> 

I think I'm starting to get this. Conventional programming languages rarely, if 
ever, 
deal with abstractions like the functor or monad. In C++ you would need 
templates to 
represent them, and templates are a lot of trouble. OO classes are the main 
form of 
abstraction I deal with.


> Those objects are the monadic values, which can be interpreted in a
> number of ways.  I like to interpret them as computations, and this is
> probably the most common interpretation.  Have a look at this:
> 
>   x :: Maybe Integer
>   x = Just 3
> 

I know Maybe is both a functor and a monad, and I was thinking: what's the 
difference? They are both wrappers on types. Then I realized, the difference 
is: they 
have different class definitions.

class Functor f where
   fmap :: (a->b) -> f a -> f b

(Note how fussy this definition would be in C++. It would be a kind of 
template, but 
would probably look a lot more complex and would require lengthy declarations.)

class Monad m where
    a >>= b :: m a -> (a -> m b) -> m b

Like functor, there are types m/f, a, and b, but they have a different 
organization.

What about my point that the definition of the >>= operator makes it useful to 
preserve access to the argument variables of earlier functions in the chain, as 
follows?

nodin = jacy >>= \finnibar ->
         keary >>= \cody ->
         return (finnibar, cody)

I suppose this is a property of structuring the code this way, and this is not 
the 
only way to structure it.


So I think what you are saying is that the esseence of the abstraction is in 
the 
definition. I think I need more experience to really understand why computer 
scientists were motivated to make that definition. After many years of OO 
programming, I immediately analyze a problem in terms of classes and objects... 
while 
monads and functors have barely entered my vocabulary.

I took a look at your tutorial, and I'll go through it in more depth.

Thanks,
Mike


------------------------------

Message: 4
Date: Mon, 13 Apr 2009 18:05:34 -0500
From: aditya siram <[email protected]>
Subject: [Haskell-beginners] RWH Ch. 27 TCP Server Example
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

Hi all,
I am trying to understand the TCP Syslog Server example [1] from RWH.
Specifically my question is on this piece of code:
          -- | Process incoming messages
          procMessages :: MVar () -> Socket -> SockAddr -> IO ()
          procMessages lock connsock clientaddr =
              do connhdl <- socketToHandle connsock ReadMode
                 hSetBuffering connhdl LineBuffering
                 messages <- hGetContents connhdl
                 mapM_ (handle lock clientaddr) (lines messages)
                 hClose connhdl
                 handle lock clientaddr
                    "syslogtcpserver.hs: client disconnected"

How does control stay on "mapM_ (handle lock clientaddr) (lines
messages)" ? It would seem that the server would handle one message
and immediately close the handle and end - but it doesn't. I'm
guessing this has something to do with laziness, but I don't see how
to apply it.

thanks ..
-deech

[1] http://book.realworldhaskell.org/read/sockets-and-syslog.html


------------------------------

Message: 5
Date: Mon, 13 Apr 2009 16:38:56 -0700
From: Arthur Chan <[email protected]>
Subject: [Haskell-beginners] How would you run a monad within another
        monad?
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="utf-8"

Hey All,

Suppose we have this generalized situation:

I have some class that does IO with user data, but we want to hide the full
IO interface, so we do something like this:

class (Monad m) => Doohickey m where
  getCurrentTime  :: m Time
  olderRecords :: m [String]
  addRecord  :: String -> m ()

Suppose next that we want to run a monadic value of that type, with some
context, inside another monad.

For example, we have some file on disk with user data.  We want the top
level to open the file, and then run a monadic action with the above
signature.   The username provides the context.  Give us a username, and
we'll open a file, and then run a monadic value w/ the above signature on
the file.  e.g.

class (Monad m) => TopLevel m where
  openFileAndRun :: (Doohickey n) => UserName -> n a -> m a

In this example, we could have a function that takes an input string s, goes
through the old records, and if it sees that s is not present, then it will
add it to the records.

Suppose then that we want to generalize the interface, so that it could
apply equally to a local file, a db, the cloud, whatever.

That's why we need the Toplevel monad.  We want to separate "what we want to
do with the user data" from "how we will store and modify the userdata".
Toplevel actions therefore needs to be able to execute Doohickey actions.

How would you guys do this?  I'm trying to write the signatures but ghc
borks on "Ambiguous type variable in the constraints" error.  It appears to
be caused by the usage of the Doohickey typeclass in the signature of
Toplevel, when I actually try to write a monadic value of type Toplevel,
that calls a monadic value of type Doohickey.

Much thanks for any help!

-Arthur
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20090413/a041eafc/attachment-0001.htm

------------------------------

Message: 6
Date: Mon, 13 Apr 2009 19:55:17 -0700
From: Jason Dusek <[email protected]>
Subject: Re: [Haskell-beginners] How would you run a monad within
        another         monad?
To: Arthur Chan <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

  Copypasting and loading your code doesn't throw an error. Please,
  pastebin an example that demonstrates the error.

--
Jason Dusek


------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 10, Issue 13
*****************************************

Reply via email to