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.  runghc question (Ian Duncan)
   2. Re:  runghc question (Jason Dusek)
   3.  a better way to do this (Michael P Mossey)
   4.  Inferred type is less polymorphic than e
      (Marco T?lio Gontijo e Silva)
   5. Re:  Inferred type is less polymorphic than e (Daniel Fischer)
   6. Re:  a better way to do this (Michael P Mossey)
   7.  STM and IO (emmanuel.delaborde)
   8. Re:  STM and IO (Quentin Moser)


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

Message: 1
Date: Wed, 8 Apr 2009 10:30:20 -0500
From: Ian Duncan <[email protected]>
Subject: [Haskell-beginners] runghc question
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes

I'm writing a script for TextMate using Haskell, and I don't know how  
to get it to work with runghc. Here's the script:

#!/usr/local/bin/runghc
 >module Main
 >where
 >import System.Cmd


 >main = putStrLn "FOO"

{- do
        c <- getContents
        system ("/Users/ian/.cabal/bin/pointfree \"" ++ c ++ "\"")
-}

How do I get it to treat this as an lhs file rather than an hs file if  
there is no extension to the filename? Is there an argument for this?

Ian Duncan


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

Message: 2
Date: Wed, 8 Apr 2009 09:05:31 -0700
From: Jason Dusek <[email protected]>
Subject: Re: [Haskell-beginners] runghc question
To: Ian Duncan <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

  Perhaps `-x` ?

       -x suffix
              Override default behaviour for source files

--
Jason Dusek


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

Message: 3
Date: Wed, 08 Apr 2009 09:24:52 -0700
From: Michael P Mossey <[email protected]>
Subject: [Haskell-beginners] a better way to do this
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

This is an early attempt to create some kind of parser, for text that is 
xml-like but not actually xml. This is probably a disaster by Haskell 
standards... If someone could point me in the direction of a better way of 
doing 
things, that would be great. I don't want to use the existing parser library, 
not at first, because I want to learn more from first principles (for now).

The input looks something like:

<entry>
   <field1> thingy </field1>
   <field2> other thingy </field2>
</entry>
<entry>
   ...
</entry>
...

where there are any number of entries. Each entry consists of a varied number 
of 
named fields. For now, the named fields can be anything--any names, in any 
order. Later I'll do sanity checking to ensure the right fields are there, to 
provide default values, etc.

This uses Data.Bytestring.Char8 for efficiency processing large files.

The output types are as follows:

type Bs = B.ByteString  -- alias
type Component = ( Bs, Bs ) -- one named field
type Entry = [ Component ] -- all named fields in one entry
type Doc = [ Entry ] -- all entries in the input document

The basic strategy is to create parsing functions, which take in a string 
(actually ByteString), and return an object, the remainder of the string, and 
an 
index. (The index indicates the position of the first character in the 
remainder 
of the string, which is useful for giving error messages.)

Top level function is called parseReqs ( "parse requirements" -- this is 
actually going to be used for a software requirements management project).

Here's the rest of the code:

-- types for regular expression matching
type Re3 = ( Bs, Bs, Bs )
type Re4 = ( Bs, Bs, Bs, [ Bs ] )

parseReqs :: Bs -> ( Doc, Bs, Int )
parseReqs buf = parseReqs' buf 0
parseReqs' :: Bs -> Int -> ( Doc, Bs, Int )
parseReqs' buf idx
   | B.null buf = ( [], buf, idx )
   | otherwise = case parseEntry buf idx  of
     (Just e, rem, remIdx)   ->
       let ( doc, rem', remIdx' ) = parseReqs' rem remIdx
       in ( e : doc, rem', remIdx' )
     (Nothing, rem, remIdx ) -> ( [], rem, remIdx )

parseEntry :: Bs -> Int -> ( Maybe Entry, Bs, Int )
parseEntry buf idx =
   let ( before, match, after ) = buf =~ "<entry>" :: Re3
       idx' = idx + B.length before + B.length match
   in if B.null match
        then ( Nothing, after, idx' )
        else let ( e, after', idx'' ) = parseEntryBody after idx'
             in ( Just e, after', idx'' )

parseEntryBody :: Bs -> Int -> ( Entry, Bs, Int )
parseEntryBody buf idx =
   let ( before, match, after ) = buf =~ "</entry>" :: Re3
       idx' = idx + B.length before + B.length match
   in if B.null match
        then error "Missing </entry>"
        else
         -- Note: index passed to parseEntryComponents is same as one passed
         -- into this function, because we pass 'before' to
         -- parseEntryComponents. Index returned from from this function is
         -- the one calculated above to occur at the start of 'after'
         ( parseEntryComponents before idx, after, idx' )

parseEntryComponents :: Bs -> Int -> Entry
parseEntryComponents buf idx =
   let ( before, match, after, groups ) = buf =~ B.pack "<([^>]+)>" :: Re4
       idx' = idx + B.length before + B.length match
   in if B.null match
        then []
        else
          let ( component, buf', idx'' ) =
                parseCompBody (head groups) after idx'
              components = parseEntryComponents buf' idx''
          in component : components

parseCompBody :: Bs -> Bs -> Int -> ( Component, Bs, Int )
parseCompBody compName buf idx =
   let ( before, match, after ) = buf =~
         (B.pack "</" `mappend` compName `mappend` B.pack ">") :: Re3
       idx' = idx + B.length before + B.length match
   in if B.null match
      then error ("No ending to component " ++ B.unpack compName)
      else ( ( compName, before ), after, idx' )


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

Message: 4
Date: Wed, 08 Apr 2009 19:29:24 -0300
From: Marco T?lio Gontijo e Silva <[email protected]>
Subject: [Haskell-beginners] Inferred type is less polymorphic than e
To: [email protected]
Message-ID: <1239229764.6067.86.ca...@zezinho>
Content-Type: text/plain

Hello,

I'm getting this error message from GHC in the following code:


> type M a = Monad m => m a

> class A a b where
>   f :: Monad m => a -> m b

> instance A String Char where
>   f string = return $ head string

> instance A Char Int where
>   f int = return $ fromEnum int

I thought at first to write h like this, but it gives me the error.  If
I write it like the other h uncommented, there's no error.  I can't see
why they aren't equivalent.

h :: IO ()
h = f "abc" >>= (f :: Char -> M Int) >>= print

> h :: IO ()
> h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ())

Can someone clarify this to me?

Greetings.

-- 
marcot
http://marcot.iaaeee.org/




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

Message: 5
Date: Thu, 9 Apr 2009 01:55:22 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Inferred type is less polymorphic
        than e
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-15"

Am Donnerstag 09 April 2009 00:29:24 schrieb Marco TĂșlio Gontijo e Silva:
> Hello,
>
> I'm getting this error message from GHC in the following code:
> > type M a = Monad m => m a
> >
> > class A a b where
> >   f :: Monad m => a -> m b
> >
> > instance A String Char where
> >   f string = return $ head string
> >
> > instance A Char Int where
> >   f int = return $ fromEnum int
>
> I thought at first to write h like this, but it gives me the error.  If
> I write it like the other h uncommented, there's no error.  I can't see
> why they aren't equivalent.
>
> h :: IO ()
> h = f "abc" >>= (f :: Char -> M Int) >>= print
>
> > h :: IO ()
> > h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ())
>
> Can someone clarify this to me?
>
> Greetings.

The first error message when loading that code is

Inferred.hs:3:0:
    Illegal polymorphic or qualified type:
      forall (m :: * -> *). (Monad m) => m a
    Perhaps you intended to use -XRankNTypes or -XRank2Types
    In the type synonym declaration for `M'                 

That can be a hint. The type synonym M is probably not what you think.

This:
----------------------------------------------------------------
class B a b where
    foo :: a -> M b

instance B String Char where
    foo str = return $ head str

instance B Char Int where
    foo c = return $ fromEnum c

k :: IO ()
k = foo "abc" >>= (foo :: Char -> M Int) >>= print
----------------------------------------------------------------

works, as does

m = foo "abc" >>= (foo :: Char -> (forall x. Monad x => x Int)) >>= print

And that reveals what's going on, since m is in fact the same as k.
The type of f in class A says that given any specific monad m and a value of 
type a, f can produce a value of type m b.
But when you write
(f :: Char -> M Int)
, you say that given a Char, f produces a value which belongs to m Int *for 
every monad m*. Thus the type you state for f (the expected type) is more 
polymorphic than the actual type f has according to the class definition (which 
is the inferred type).



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

Message: 6
Date: Wed, 08 Apr 2009 17:07:35 -0700
From: Michael P Mossey <[email protected]>
Subject: Re: [Haskell-beginners] a better way to do this
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Michael P Mossey wrote:
> This is an early attempt to create some kind of parser, for text that is 
> xml-like but not actually xml. This is probably a disaster by Haskell 
> standards... If someone could point me in the direction of a better way 
> of doing things, that would be great. I don't want to use the existing 
> parser library, not at first, because I want to learn more from first 
> principles (for now).
> 

To follow up my own post, I'm working through chapter 10 of "Real World 
Haskell" 
right now, and then I'll look at chapter 14 (Monads). I think this is a better 
way of creating parsers. Maybe I'll look at Parsec eventually too, although I 
want to do a lot of stuff myself for the learning exprience.

Thanks,
Mike


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

Message: 7
Date: Thu, 9 Apr 2009 10:33:35 +0100
From: "emmanuel.delaborde" <[email protected]>
Subject: [Haskell-beginners] STM and IO
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes

Hello list

I am trying to use STM for shared access to a file

I first used a TVar to to accumulate the text returned by the threads
and write TVar's content to a file after a delay (how do you ensure  
all threads have terminated by the way, that would be more robust than  
using an arbitrary delay)


-- this works
main = do
     let fname = "store.txt"
     store <- atomically $ newTVar ""
     forkIO $ 10 `replicateM_` (thread store)
     threadDelay 800000
     txt <- atomically (readTVar store)
     writeFile fname txt

thread :: TVar (String) -> IO ()
thread store = atomically ( readTVar store >>= writeTVar store . (++ "  
some text "))


But when I try to concurrently write to the file, I get into troubles.
I keep the file handle in a TMVar, hoping than just one thread at a  
time will be able to use that handle
but nothing gets written to "store.txt" ? Is my IO too lazy ?


-- this does not work
main = do
    let fname = "store.txt"
    fh <- openFile fname ReadWriteMode
    store <- atomically $ newTMVar fh
    forkIO $ 10 `replicateM_` (writeTo store)

writeTo :: TMVar (Handle) -> IO ()
writeTo store = do
    fh <- atomically $ takeTMVar store
    text <- hGetContents fh
    hPutStr fh (text ++ " some text ")
    atomically $ putTMVar store fh


Thank you

--
Emmanuel Delaborde

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

This e-mail (and any attachments) is confidential and may contain 
personal views which are not the views of Cimex Media Ltd and 
any affiliated companies, unless specifically stated. It is intended 
for the use of the individual or group to whom it is addressed. If 
you have received it in error, please delete it from your system, 
do not use, copy or disclose the information in any way nor act in 
reliance on it and please notify [email protected]

A company registered in England  Wales. Company Number 03765711
Registered Office : The Olde Bakehouse, 156 Watling Street East, Towcester,
Northants NN12 6DB

This email was scanned by Postini, the leading provider in Managed Email 
Security.



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

Message: 8
Date: Thu, 9 Apr 2009 12:03:03 +0200
From: Quentin Moser <[email protected]>
Subject: Re: [Haskell-beginners] STM and IO
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=US-ASCII

On Thu, 9 Apr 2009 10:33:35 +0100
"emmanuel.delaborde" <[email protected]> wrote:

> Hello list
> 
> I am trying to use STM for shared access to a file
> 
> I first used a TVar to to accumulate the text returned by the threads
> and write TVar's content to a file after a delay (how do you ensure  
> all threads have terminated by the way, that would be more robust
> than using an arbitrary delay)
> 
> 
> -- this works
> main = do
>      let fname = "store.txt"
>      store <- atomically $ newTVar ""
>      forkIO $ 10 `replicateM_` (thread store)
>      threadDelay 800000
>      txt <- atomically (readTVar store)
>      writeFile fname txt
> 
> thread :: TVar (String) -> IO ()
> thread store = atomically ( readTVar store >>= writeTVar store . (++
> " some text "))
> 
> 
> But when I try to concurrently write to the file, I get into troubles.
> I keep the file handle in a TMVar, hoping than just one thread at a  
> time will be able to use that handle
> but nothing gets written to "store.txt" ? Is my IO too lazy ?
> 
> 
> -- this does not work
> main = do
>     let fname = "store.txt"
>     fh <- openFile fname ReadWriteMode
>     store <- atomically $ newTMVar fh
>     forkIO $ 10 `replicateM_` (writeTo store)
> 
> writeTo :: TMVar (Handle) -> IO ()
> writeTo store = do
>     fh <- atomically $ takeTMVar store
>     text <- hGetContents fh
>     hPutStr fh (text ++ " some text ")
>     atomically $ putTMVar store fh
> 
> 
> Thank you
> 

Your problem has nothing to do with lazyness; Haskell simply kills all
other threads when the main thread returns from main. You have to
somehow wait for them to complete in main or they won't have time to
run.

As strange as it seems, I don't think the standard libraries provide an
easy way to do this, but you can implement it yourself.

Here's an example inspired by the documentation of Control.Concurrent:

> import Control.Concurrent
> import Control.Exception (finally)
>
> myFork :: IO () -> IO (MVar ())
> myFork a = do v <- newEmptyMVar
>               a `finally` (putMVar v ())
>
> myWait :: MVar () -> IO ()
> myWait = readMVar

With this, you could rewrite your main like this:

> main = do
>     let fname = "store.txt"
>     fh <- openFile fname ReadWriteMode
>     store <- atomically $ newTMVar fh
>     waitMe <- myFork $ 10 `replicateM_` (writeTo store)
>     myWait waitMe


Now onto the second problem: ignore me if I'm wrong, but it seems your
intent is to spawn 10 threads that will each try to run (writeTo store)
once. What your current code does is spawn one thread that sequentially
runs writeTo 10 times.

To create 10 threads, you should fork inside the replicateM, not
outside. Here's how you could correct this (again using myFork and
myWait from above):

> main = do
>     let fname = "store.txt"
>     fh <- openFile fname ReadWriteMode
>     store <- atomically $ newTMVar fh
>     waitMes <- 10 `replicateM` (myFork $ writeTo store))
>     mapM_ myWait waitMes

(make sure you use replicateM and not replicateM_ or you'll get a type
error)


Note: I haven't tried running any of this code, but it seems simple
enough to be confident in.


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

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


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

Reply via email to