Send Beginners mailing list submissions to
        beginners@haskell.org

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
        beginners-requ...@haskell.org

You can reach the person managing the list at
        beginners-ow...@haskell.org

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


Today's Topics:

   1. Re:  Bytestring question (Daniel Fischer)
   2. Re:  Bytestring question (Peter Braun)
   3.  Looking for some Haskell Monad Code Examples (patricklynch)
   4. Re:  Looking for some Haskell Monad Code Examples (aditya siram)
   5. Re:  Looking for some Haskell Monad Code Examples
      (Henk-Jan van Tuyl)
   6. Re:  Looking for some Haskell Monad Code Examples
      (Karol Samborski)
   7.  Trying to use map (Michael Litchard)
   8. Re:  Trying to use map (Daniel Fischer)


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

Message: 1
Date: Wed, 26 Jan 2011 14:28:25 +0100
From: Daniel Fischer <daniel.is.fisc...@googlemail.com>
Subject: Re: [Haskell-beginners] Bytestring question
To: beginners@haskell.org
Message-ID: <201101261428.25915.daniel.is.fisc...@googlemail.com>
Content-Type: text/plain;  charset="iso-8859-1"

On Wednesday 26 January 2011 01:52:33, Peter Braun wrote:
> Hi everyone,
>
> as an exercise for learning Haskell i'm writing a program that converts
> Ascii Stl files (a simple format for 3D model data) into binary Stl
> format. In my first attempt i used normal strings and the result was
> therefore very slow. Now i rewrote the program to use lazy bytestrings
> instead.
>
> But well... it got even slower, so i'm probably doing something terribly
> wrong ;)
>
> Here's what i do (the relevant parts):
>
> ...
> asciiFile <- L.readFile (args!!0)
> binHandle <- openBinaryFile (args!!1) WriteMode
> let asciiLines = L.split (c2w '\n') asciiFile
> ...
> parseFile binHandle (Normal, tail asciiLines) -- First line contains a
> comment
> ...
>
> where L is Data.ByteString.Lazy. readFile ought to be lazy so it should
> not read the whole file into ram at this point. But when i split the
> lines and pass them to a function, is this still carried out lazily?

Yes, readFile reads a chunk and only proceeds to read the next when it is 
required. I'm not sure how lazy split is exactly, it could stop at the 
first newline or it could split the entire chunk in one go, but that 
wouldn't make much difference either way.

>
> parseFile processes a line, depending on the StlLineType and then calls
> itself recursive like this:
>
> parseFile :: Handle -> (StlLineType, [L.ByteString]) -> IO ()

Shouldn't the type better be

parseFile :: Handle -> StlLineType -> [L.ByteString] -> IO ()

?

> ...
> parseFile h (Vertex1, s) = do
>      let vals = extractVertex (head s)
>      L.hPutStr h $ runPut (writeFloatArray vals)
>      parseFile h (Vertex2, tail s)

pattern match, please

parseFile h (Vertex1, []) = return () -- or what you have to do at the end
parseFile h (Vertex1, (l:ls)) = do
    let vals = extractVertex l
    L.hPutStr $ runPut (writeFloatArray vals)
    parseFile h (Vertex2, ls)

> ...
>
> extractVertex looks like this:
>
> extractVertex :: L.ByteString -> [Float]
> extractVertex s = let fracs = filter (\n -> L.length n > 0) $ L.split
> (c2w ' ') s
>                                      in    [read (C.unpack(fracs!!1)) ::
> Float,

Ouch, if you're unpacking everything, what's the point of using 
ByteStrings? And splitting ByteStrings is sort of expensive too.

Okay, trouble is, there's no obvious way to parse a Float from a 
ByteString, but bytestring-lexing provides parsing Doubles, you could use 
that and convert the Doubles to Floats with GHC.Float.double2Float (or, if 
you have optimisations turned on, with realToFrac, which should then be 
rewritten to double2Float). That should be much faster than unpacking and 
using read (particularly since the Read instances of Float and Double are 
slow).

>                                              read (C.unpack(fracs!!2))
>
> :: Float,
>
>                                              read (C.unpack(fracs!!3))
>
> :: Float]

Instead of list-indexing with (!!), pattern matching gives nicer code.

>
> where C is Data.ByteString.Lazy.Char8. It splits a byte string, filters
> out the whitespaces and converts certain entries to floats. Maybe unpack
> is an expensive operation. Is there a better way to convert a Bytestring
> to float?

You could also try using attoparsec and write a real parser for your file, 
that should be pretty snappy. attoparsec also provides

double :: Parser Double

(no direct parsing of Float provided), you could then again call 
double2Float on the result.

>
> I know, this is bad Haskell code ;) But where is my grand, obvious
> misuse of Bytestring?

Lots of splitting into small pieces and lots of unpacking. Both add up to 
considerable cost. I suspect also read to take a substantial amount of the 
time, but you also have that for String IO.

>
> I'm grateful for any suggestion to improve that code. I'm using ghc,
> version 6.12.1.
>
> Thank you,
> Peter




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

Message: 2
Date: Wed, 26 Jan 2011 19:37:18 +0100
From: Peter Braun <peter-br...@gmx.net>
Subject: Re: [Haskell-beginners] Bytestring question
To: beginners@haskell.org
Message-ID: <4d4069de.2030...@gmx.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Thanks for your reply. Attoparsec seems to be the perfect tool for the 
job and i will ultimately try to implement my converter utilizing it. 
But i also installed bytestring-lexing and will try this out, just to 
see if i can gain some performance when eliminating the suboptimal reads 
/ unpacks. Thanks for the tip!

Shouldn't the type better be

parseFile :: Handle ->  StlLineType ->  [L.ByteString] ->  IO ()

Yes, there really is no reason for using a tuple. I'll also eliminate 
the usage of (!!) and function calls where pattern matching is possible.



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

Message: 3
Date: Wed, 26 Jan 2011 15:41:43 -0500
From: "patricklynch" <kmandpjly...@verizon.net>
Subject: [Haskell-beginners] Looking for some Haskell Monad Code
        Examples
To: <beginners@haskell.org>
Message-ID: <657fe5f6dc4b46cf87a5a89391aae...@stsv.com>
Content-Type: text/plain; charset=US-ASCII

Good afternoon,

...can anyone provide me with a references that shows Haskell code examples
of Monads?

... I've read the references but I need some actual code snippets to check
to see if I really understand Monads.

Thank you




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

Message: 4
Date: Wed, 26 Jan 2011 14:19:26 -0600
From: aditya siram <aditya.si...@gmail.com>
Subject: Re: [Haskell-beginners] Looking for some Haskell Monad Code
        Examples
To: patricklynch <kmandpjly...@verizon.net>
Cc: beginners@haskell.org
Message-ID:
        <aanlktik7euj2xmks2siqh38z-p+yittffsp3dzrkf...@mail.gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

Learn You A Haskell [1]  and Real World Haskell [2] are great resources.
-deech

[1] http://learnyouahaskell.com/a-fistful-of-monads
[2] http://book.realworldhaskell.org/read/monads.html


On Wed, Jan 26, 2011 at 2:41 PM, patricklynch <kmandpjly...@verizon.net> wrote:
> Good afternoon,
>
> ...can anyone provide me with a references that shows Haskell code examples
> of Monads?
>
> ... I've read the references but I need some actual code snippets to check
> to see if I really understand Monads.
>
> Thank you
>
>
> _______________________________________________
> Beginners mailing list
> Beginners@haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



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

Message: 5
Date: Wed, 26 Jan 2011 22:20:17 +0100
From: "Henk-Jan van Tuyl" <hjgt...@chello.nl>
Subject: Re: [Haskell-beginners] Looking for some Haskell Monad Code
        Examples
To: beginners@haskell.org, patricklynch <kmandpjly...@verizon.net>
Message-ID: <op.vpxpj3xypz0...@zen5.arnhem.chello.nl>
Content-Type: text/plain; charset=iso-8859-15; format=flowed;
        delsp=yes

On Wed, 26 Jan 2011 21:41:43 +0100, patricklynch  
<kmandpjly...@verizon.net> wrote:

> Good afternoon,
>
> ...can anyone provide me with a references that shows Haskell code  
> examples
> of Monads?

See "A tour of the Haskell Monad functions":
   http://members.chello.nl/hjgtuyl/tourdemonad.html

Regards,
Henk-Jan van Tuyl


-- 
http://Van.Tuyl.eu/
http://members.chello.nl/hjgtuyl/tourdemonad.html
--



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

Message: 6
Date: Wed, 26 Jan 2011 22:44:32 +0100
From: Karol Samborski <edv.ka...@gmail.com>
Subject: Re: [Haskell-beginners] Looking for some Haskell Monad Code
        Examples
To: patricklynch <kmandpjly...@verizon.net>
Cc: beginners@haskell.org
Message-ID:
        <AANLkTi=0riMuUVGQ=jpff9qazg1j2okjkyrgbx8h7...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

I'm a Haskell beginner and monads become clear to me after reading the
"Real World Haskell" book so I fully recommend it ;)

Regards,
Karol Samborski

2011/1/26 patricklynch <kmandpjly...@verizon.net>:
> Good afternoon,
>
> ...can anyone provide me with a references that shows Haskell code examples
> of Monads?
>
> ... I've read the references but I need some actual code snippets to check
> to see if I really understand Monads.
>
> Thank you
>
>
> _______________________________________________
> Beginners mailing list
> Beginners@haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



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

Message: 7
Date: Wed, 26 Jan 2011 14:51:18 -0800
From: Michael Litchard <mich...@schmong.org>
Subject: [Haskell-beginners] Trying to use map
To: beginners@haskell.org
Message-ID:
        <AANLkTinh6U0gehJAKT4ky5t=bwehdmxiatbrhvczt...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

Here's what I'm working with, followed by what I am trying to do, and the
type error I get. I'm leaving things out that I do not think are important.
Let me know if I'm missing nessecary info.

> curlResp
>   :: (MonadError String m, MonadIO m)
>   => Curl -> URLString -> [CurlOption] -> m String --CurlResponse
> curlResp curl url opts = do
>   resp <- liftIO $ (do_curl_ curl url opts :: IO CurlResponse)
>   let code   = respCurlCode resp
>       status = respStatus resp
>   if code /= CurlOK || status /= 200
>      then throwError $ "Error: " ++ show code ++ " -- " ++ show status
>      else return $ respBody resp

> screenScraping :: String -> [String]
> screenScraping responseBody =
>                let collectedStrings = processHTML responseBody
>                    collectedIDLists = createIDList collectedStrings
>                    in constructedResourceURIs urlBase collectedIDLists

> resourceOpts :: [CurlOption]
> resourceOpts =
>   [ CurlHttpHeaders
>     [ "Accept: text/javascript, text/html, application/xml, text/xml, */*"
>     , "Accept-Language: en-us,en;q=0.5"
>     , "Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7"
>     , "Keep-Alive:      115"
>     , "Connection:      keep-alive"
>     , "X-Requested-With:        XMLHttpRequest"
>     , "X-Prototype-Version:     1.6.0.3"
>     ]
>     , CurlEncoding "gzip,deflate"
>   ]



> obtainCookies :: IO Curl -> String -> IO ()
> obtainCookies curl responseBody = do
>               curl' <- curl
>               let collectedResources = screenScraping responseBody
>                   in mapM ( curlResp curl' resourceOpts)
collectedResources
>               return ()

> main :: IO ()
> main = do
>   curl <- initCurl
>   user:pass:_ <- getArgs
>   resp <- generateResourceHtml user pass
>
>   case resp of
>     Left err -> print err
>     Right body -> obtainCookies curl body

Here's the error I get.

    Couldn't match expected type `Char'
           against inferred type `CurlOption'
      Expected type: URLString
      Inferred type: [CurlOption]
    In the second argument of `curlResp', namely `resourceOpts'
    In the first argument of `mapM', namely
        `(curlResp curl' resourceOpts)'


The problem I see is a misformed mapM.

I am trying to do something like this


curlResp curl' resourceOpts "-here-be-a-url"

where collectedResources is a [String]. Not sure how to map over it
correctly.

The other problem I see is this
> obtainCookies :: IO Curl -> String -> IO ()
> obtainCookies curl responseBody = do
>               curl' <- curl
>               let collectedResources = screenScraping responseBody
>                   in mapM ( curlResp curl' resourceOpts)
collectedResources
>               return ()

this function does a monadic action (all I want is the cookies) and I don't
need the return value. I am not sure that the final line return (), is what
I want.


My primary question is this. how do I map over collectedResources correctly?
Secondary question, is the return correct?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110126/eba919f5/attachment-0001.htm>

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

Message: 8
Date: Thu, 27 Jan 2011 00:13:51 +0100
From: Daniel Fischer <daniel.is.fisc...@googlemail.com>
Subject: Re: [Haskell-beginners] Trying to use map
To: beginners@haskell.org
Message-ID: <201101270013.51978.daniel.is.fisc...@googlemail.com>
Content-Type: text/plain;  charset="utf-8"

On Wednesday 26 January 2011 23:51:18, Michael Litchard wrote:
> Here's what I'm working with, followed by what I am trying to do, and
> the type error I get. I'm leaving things out that I do not think are
> important. Let me know if I'm missing nessecary info.
> >
> >
> > obtainCookies :: IO Curl -> String -> IO ()
> > obtainCookies curl responseBody = do
> >               curl' <- curl
> >               let collectedResources = screenScraping responseBody
> >                   in mapM ( curlResp curl' resourceOpts)
>
> collectedResources
>

Looks like you need a flip here:

           in mapM (flip (curlResp curl') resourceOpts) collectedResources

> >               return ()

If you're throwing away the results of the MapM'ed actions, use mapM_

obtainCookies curl responseBody = do
    curl' <- curl
    mapM_ (flip (curlResp curl') resourceOpts) $
          screenScraping responseBody

>
> this function does a monadic action (all I want is the cookies) and I
> don't need the return value. I am not sure that the final line return
> (), is what I want.
>
>
> My primary question is this. how do I map over collectedResources
> correctly? Secondary question, is the return correct?

Use mapM_




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

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 31, Issue 33
*****************************************

Reply via email to