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.  example of compostion (Rainer Grimm)
   2. Re:  Any advice on installing gtk2hs (patricklynch)
   3. Re:  example of compostion (Ozgur Akgun)
   4. Re:  Any advice on installing gtk2hs (Daniel Fischer)
   5. Re:  Any advice on installing gtk2hs (Krzysztof Skrz?tnicki)
   6.  Almost there. Bizzaro problem with libcurl forces kludge
      that I would like to be rid of. (Michael Litchard)


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

Message: 1
Date: Mon, 31 Jan 2011 22:15:18 +0100
From: Rainer Grimm <rai...@grimm-jaud.de>
Subject: [Haskell-beginners] example of compostion
To: beginners@haskell.org
Message-ID: <4d472666.9080...@grimm-jaud.de>
Content-Type: text/plain; charset="iso-8859-15"

Hello,
I'm looking for a good example of function composition. It's very
impressive, how concise you can extract information out of a file in
Haskell. So I write a short programm, which gets all title words out of
a given file sorted by their length.
How could the following programm be improved?


import Data.Char (isUpper,isLower)
import Data.List (sortBy)
import Data.Ord (comparing)

isTitle word=  
  isFirstUpperCase ( word) && isTailLowerCase ( word )
  where isFirstUpperCase= isUpper . head
    isTailLowerCase= all isLower . tail

main = do
  putStrLn "The name of the input file:"
  file <- getLine
  inputString <- readFile file
  let allTitles= reverse . sortBy (comparing length ) . filter isTitle $
words inputString
  putStrLn $ show $ take 15  allTitles
  putStrLn $ show (length allTitles) ++ " titles in " ++ file


Thanks in advance,
Rainer

-- 
Rainer Grimm  rai...@grimm-jaud.de
              http://www.grimm-jaud.de


<javascript:void(0);>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/e3df3b8d/attachment-0001.htm>

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

Message: 2
Date: Mon, 31 Jan 2011 17:25:08 -0500
From: "patricklynch" <kmandpjly...@verizon.net>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: <beginners@haskell.org>
Message-ID: <77c8062e93bc405990ed69e0b516a...@stsv.com>
Content-Type: text/plain; charset="us-ascii"

To Aditya Siram

 

...thanks for writing the procedure in the link in the email below......

...I got stuck on the command: 'cabal install gtk'

...it gives the following message:

 

Linking:

C:\Users\User\AppData\Local\cairo-0.12.043\cairo-0.12\dist\setup\setup.exe

...

Cannot find gtk2hsC2hs

Please install 'gtk2hs-buildtools' first and check that the install

Directory is in your PATH (e.g.. HOME/.cabal/bin)

 

My PATH is C:/Users/User/AppData/Roaming/cabal/bin

Should I change my PATH?

 

Good day

 

-----Original Message-----
From: patricklynch [mailto:kmandpjly...@verizon.net] 
Sent: Monday, January 31, 2011 1:55 PM
To: 'patricklynch'; beginners@haskell.org
Subject: RE: Any advice on installing gtk2hs

 

PS, this was for the Windows installation...

 

-----Original Message-----
From: patricklynch [mailto:kmandpjly...@verizon.net] 
Sent: Monday, January 31, 2011 1:54 PM
To: 'beginners@haskell.org'
Subject: Any advice on installing gtk2hs

 

Good afternoon,

 

Any advice on installing gtk2hs...

I used the instructions at: http://www.haskell.org/haskellwiki/Gtk2Hs and
get a bunch of error messages...

 

Thanks...

 

 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 6144 bytes
Desc: not available
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/3c9b09d6/attachment-0001.bin>

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

Message: 3
Date: Mon, 31 Jan 2011 22:04:59 +0000
From: Ozgur Akgun <ozgurak...@gmail.com>
Subject: Re: [Haskell-beginners] example of compostion
To: Rainer Grimm <rai...@grimm-jaud.de>
Cc: beginners@haskell.org
Message-ID:
        <AANLkTi=v72jz7rebkmhqw9txy8d7y8jt0u3v-ohzj...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

On 31 January 2011 21:15, Rainer Grimm <rai...@grimm-jaud.de> wrote:

> isTitle word=
>   isFirstUpperCase ( word) && isTailLowerCase ( word )
>   where isFirstUpperCase= isUpper . head
>     isTailLowerCase= all isLower . tail
>

One possible improvement is using pattern matching while defining isTitle.

isTitle []     = False -- I suppose?
isTitle (x:xs) = isUpper x && all isLower xs

-- 
Ozgur
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/22056b24/attachment-0001.htm>

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

Message: 4
Date: Mon, 31 Jan 2011 23:11:50 +0100
From: Daniel Fischer <daniel.is.fisc...@googlemail.com>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: beginners@haskell.org
Message-ID: <201101312311.51202.daniel.is.fisc...@googlemail.com>
Content-Type: text/plain;  charset="utf-8"

On Monday 31 January 2011 23:25:08, patricklynch wrote:
> To Aditya Siram
>
>
>
> ...thanks for writing the procedure in the link in the email below......
>
> ...I got stuck on the command: 'cabal install gtk'
>
> ...it gives the following message:
>
>
>
> Linking:
>
> C:\Users\User\AppData\Local\cairo-0.12.043\cairo-0.12\dist\setup\setup.e
>xe
>
> ...
>
> Cannot find gtk2hsC2hs
>
> Please install 'gtk2hs-buildtools' first and check that the install
>
> Directory is in your PATH (e.g.. HOME/.cabal/bin)
>

Have you done 'cabal install gtk2hs-buildtools' first?
That step is not listed under point 5.1.5, that may be an oversight.

If you have, where is gtk2hsC2hs located, is it in 
C:/Users/User/AppData/Roaming/cabal/bin or elsewhere?

>
>
> My PATH is C:/Users/User/AppData/Roaming/cabal/bin
>
> Should I change my PATH?
>
>
>
> Good day
>
>



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

Message: 5
Date: Mon, 31 Jan 2011 23:05:33 +0100
From: Krzysztof Skrz?tnicki <gte...@gmail.com>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: patricklynch <kmandpjly...@verizon.net>
Cc: beginners@haskell.org
Message-ID:
        <AANLkTik1u256SFSGoRvvuHFSGrJByzvp=YwDC=xkr...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

>
>
> Cannot find gtk2hsC2hs
>
> Please install 'gtk2hs-buildtools' first and check that the install
>
> Well, did you follow the message with 'cabal install gtk2hs-buildtools'
then?

Best regards,
Krzysztof Skrz?tnicki
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/8e30b64b/attachment-0001.htm>

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

Message: 6
Date: Mon, 31 Jan 2011 14:42:30 -0800
From: Michael Litchard <mich...@schmong.org>
Subject: [Haskell-beginners] Almost there. Bizzaro problem with
        libcurl forces kludge that I would like to be rid of.
To: beginners@haskell.org
Message-ID:
        <AANLkTinoG0=-bXLr6uerNw-bhYMEmi1zvWvr=n6e+...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

So, I've been writing a http client designed to simulate a session with one
of my company's products.
The crucial thing we need from this program is a cookie jar. When I began I
was doing exploratory code to figure things out about http. I managed to
make a cookie jar with my toy code, along with the intermediate steps needed
to generate the cookies that represent a session.
Then it was time to integrate my experimental toy code into something closer
to what production code should look like.
This is where bizarro behavior starts to happen. All the intermediate steps
appear to be working, as later steps are dependent on earlier steps
succeeding. Yet in the end, no cookie jar.

We did an strace on the binary and it appears that there seems to be a
problem with the reading/writing of  the file to be the cookie jar, and we
don't know why. The kludge solution is to write a wrapper that calls the
program in such a way that I can capture standard error and parse out the
cookies. I would hate for things to remain this way. It disturbs me.


So, my toy code can create a cookie jar. But what will one day be production
code does everything correctly except produce the cookie jar. Included is
the entire program, standard error, and strace output. Also, my toy program
which succeeds in producing a cookie jar. If anyone wants to take a stab at
this that would be peachy. I'm looking for avenues to explore and good
questions to ask, as I am out of both.

P.S. Thanks to everyone who got me this far. If this is what we end up
having to use, it does get the job done. I'm just trying to get rid of my
kludge work-around.


> {-# LANGUAGE FlexibleContexts #-}
> module Main where

------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

> import Control.Monad
> import Control.Monad.Error
> import Network.Curl
> import System.Environment (getArgs)
> import HtmlParsing
> import SessionCreator

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


> {-# LANGUAGE FlexibleContexts #-}
> module SessionCreator
>     (
>       initCurl,
>       curlResp,
>       urlBase,
>       urlInitial,
>       urlLogin,
>       urlLogOut,
>       urlFlash1,
>       urlFlash2,
>       urlLaunch,
>       urlLaunchTest,
>       urlQuickCreate,
>       urlGetResource,
>       urlShowWebForwards,
>       respBody,
> --      login
>       resourceOpts,
>       loginOpts
>     ) where

------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

--import qualified Data.ByteString as B

> import Network.Curl
> import Control.Monad
> import Control.Monad.Error

> initCurl :: IO Curl
> initCurl = do
>   curl <- initialize
>   setopts curl curlOpts
>   return curl

> curlOpts :: [CurlOption]
> curlOpts =
>   [ CurlCookieSession True
>   , CurlCookieJar  "cookies.txt"
>   , CurlCookieFile "cookies2.txt"
>   , CurlFollowLocation True
>   , CurlUserAgent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
>   , CurlVerbose True
>   , CurlHeader True
>   , CurlAutoReferer True
>   , CurlFailOnError True
>   ]


> --- loginOpts looks like this for now
> loginOpts :: String -> String -> [CurlOption]
> loginOpts user pass =
>   [ CurlFailOnError True
>   , CurlPost True
>   , CurlNoBody False
>   , CurlPostFields
>     [ "_charset_=UTF-8"
>     , "javaScript=true"
>     , "username=" ++ user
>     , "password=" ++ pass
>     ]
>   ]

> 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"
>   ]


> curlResp :: (Error e, MonadError e 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 $ strMsg $ "Error: " ++ show code ++ " -- " ++ show
status
>      else return $ respBody resp


------------------------------------------------------------------------------
   URLs
------------------------------------------------------------------------------

> (//) :: String -> String -> String
> a // b = a ++ "/" ++ b

> urlBase :: URLString
> urlBase = "https://172.16.1.18";

> urlInitial = urlBase // "showLogon.do"
> urlLogin   = urlBase // "default/showLogon.do"
> urlFlash1  = urlBase // "showFlashCheck.do"
> urlFlash2  = urlBase // "logon.do?flashVersion=10.1.102"
> urlShowWebForwards = urlBase // "showWebForwards.do"
> urlGetResource  = urlBase //
"resourceList.do?form=webForwardsForm&readOnly=false&policyLaunching=true&resourcePrefix=webForwards&path=%2FshowWebForwards.do&messageResourcesKey=webForwards&actionPath=%2FresourceList.do"

> urlCreateWebForward = urlBase //
"quickCreateWebForward.do?actionTarget=create&actionPath=%2FquickCreateWebForward.do%3FactionTarget%3Dcreate&quickCreate=true&evalJS=true&evalScripts=true"


> urlLogOut = urlBase // "logoff.do"


> urlQuickCreate = urlBase //
"quickCreateWebForward.do?actionTarget=create&actionPath=%2FquickCreateWebForward.do%3FactionTarget%3Dcreate&quickCreate=true&evalJS=true&evalScripts=true"




> module HtmlParsing
>     (
>       obtainCookies
>      ,generateResourceHtml
>     ) where

> import Text.HTML.TagSoup
> import Data.List.Split
> import Data.List
> import Data.Maybe
> import Numeric
> import Network.Curl
> import Control.Monad
> import Control.Monad.Error
> import SessionCreator


> processHTML :: String -> [[String]]
> processHTML htmlFILE =
>            let parsedHTML        = parseTags htmlFILE
>                allTagOpens       = sections (~== TagOpen "a"
[("href","")]) parsedHTML
>                taggedTEXT        = head $ map (filter isTagOpen)
allTagOpens
>                allHREFS          = map (fromAttrib "href") taggedTEXT
>                allPotentials     = map (dropWhile (/= '?')) allHREFS
>                removedNulls      = filter (not . null) allPotentials
>                removedQs         = map (drop 1) removedNulls
>            in map (splitOn "&") removedQs

> createIDList :: [[String]] -> [String]
> createIDList strungPairs =
>              let nvList = map (map (splitOn "=")) strungPairs
>                  nvTuple = map (map (list2Tuple)) nvList
>                  netofResources =  map (lookup "resourceId") nvTuple
>                  removedNothings = catMaybes netofResources
>                  sortedIds = (map head . group . sort) $ map (\x -> read x
:: Int) removedNothings
>              in  map ("ResourceId" %%) $ map show sortedIds

> list2Tuple :: [a] -> (a,a)
> list2Tuple [x,y] = (x,y)


> (%%) :: String -> String -> String
> a %% b = a ++ "=" ++ b



> generateResourceHtml :: Curl -> String -> String -> IO (Either String
String)
> generateResourceHtml curl user pass = do
>   let makeIDPage = do
>       curlResp curl urlInitial method_GET
>       curlResp curl urlLogin $ loginOpts user pass
>       curlResp curl urlFlash1 resourceOpts
>       curlResp curl urlFlash2 resourceOpts
>       curlResp curl urlShowWebForwards resourceOpts
>       curlResp curl urlQuickCreate resourceOpts
>       curlResp curl urlGetResource resourceOpts
>   runErrorT makeIDPage


> obtainCookies :: Curl -> String -> IO ()
> obtainCookies curl responseBody = do
>               mapM_ (flip (curlResp curl) resourceOpts) $
>                     screenScraping responseBody

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


> constructedResourceURIs :: String -> [String] -> [String]
> constructedResourceURIs url resourceIDs =
>                         let frontURI = url ++ "/launchWebForward.do?"
>                             midURI = map (frontURI ++) resourceIDs
>                         in map (++
"&policy=0&returnTo=%2FshowWebForwards.do") midURI


Here is the toy (produces a cookiejar) program.
Attached are all the output files

{-# LANGUAGE FlexibleContexts #-}
module Main where

------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

import Control.Monad
import Control.Monad.Error
import Network.Curl
import System.Environment (getArgs)

------------------------------------------------------------------------------
-- Curl
------------------------------------------------------------------------------

initCurl :: IO Curl
initCurl = do
  curl <- initialize
  setopts curl curlOpts
  return curl

curlOpts :: [CurlOption]
curlOpts =
  [ CurlCookieSession True
  , CurlCookieJar  "cookies.txt"
  , CurlCookieFile "cookies.txt"
  , CurlFollowLocation True
  , CurlUserAgent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
  , CurlVerbose True
  ]

loginOpts :: String -> String -> [CurlOption]
loginOpts user pass =
  [ CurlFailOnError True
  , CurlPost True
  , CurlNoBody False
  , CurlPostFields
    [ "_charset_=UTF-8"
    , "javaScript=true"
    , "username=" ++ user
    , "password=" ++ pass
    ]
  ]

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

------------------------------------------------------------------------------
-- URLs
------------------------------------------------------------------------------

(//) :: String -> String -> String
a // b = a ++ "/" ++ b

urlBase :: URLString
urlBase = "https://172.16.1.18";

urlInitial = urlBase // "showLogon.do"
urlLogin   = urlBase // "default/showLogon.do"
urlFlash1  = urlBase // "showFlashCheck.do"
urlFlash2  = urlBase // "logon.do?flashVersion=9.0.100"
urlLaunch  = urlBase //
"launchWebForward.do?resourceId=4&policy=0&returnTo=%2FshowWebForwards.do"
urlLaunchTest = urlBase //
"launchWebForward.do?resourceId=5&policy=0&returnTo=%2FshowWebForwards.do"

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

------------------------------------------------------------------------------
-- URLs
------------------------------------------------------------------------------

(//) :: String -> String -> String
a // b = a ++ "/" ++ b

urlBase :: URLString
urlBase = "https://172.16.1.18";

urlInitial = urlBase // "showLogon.do"
urlLogin   = urlBase // "default/showLogon.do"
urlFlash1  = urlBase // "showFlashCheck.do"
urlFlash2  = urlBase // "logon.do?flashVersion=9.0.100"
urlLaunch  = urlBase //
"launchWebForward.do?resourceId=4&policy=0&returnTo=%2FshowWebForwards.do"
urlLaunchTest = urlBase //
"launchWebForward.do?resourceId=5&policy=0&returnTo=%2FshowWebForwards.do"

------------------------------------------------------------------------------
-- IO
------------------------------------------------------------------------------

launch :: String -> String -> IO (Either String String)
launch user pass = do
  -- Initialize Curl
  curl <- initCurl

  -- Sequence of steps
  let steps = do
      curlResp curl urlInitial method_GET
      curlResp curl urlLogin $ loginOpts user pass
      curlResp curl urlFlash1 method_GET
      curlResp curl urlFlash2 method_GET
      curlResp curl urlLaunch method_GET
      -- curlResp curl urlLaunchTest method_GET
      -- You'd use this to catch the exception right away
      -- `catchError` \e-> ...
  runErrorT steps

main :: IO ()
main = do
  -- username and password
  user:pass:_ <- getArgs

  -- Launch webpage
  resp <- launch user pass

  -- Response comes as Either String String
  -- You have to handle each case
  case resp of
    Left  err  -> print err
    Right body -> putStrLn body



So to sum up again, I'm trying to figure out why the toy program generates a
cookie jar and the other program does everything it should *except* produce
a cookie jar. Thanks to anyone who wants to slog through this.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: production_headers
Type: application/octet-stream
Size: 57684 bytes
Desc: not available
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: production_log
Type: application/octet-stream
Size: 1565292 bytes
Desc: not available
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: toy_headers
Type: application/octet-stream
Size: 24335 bytes
Desc: not available
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: toy_strace
Type: application/octet-stream
Size: 713169 bytes
Desc: not available
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0003.obj>

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

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


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

Reply via email to